diff --git a/build-locale-archive.c b/build-locale-archive.c new file mode 100644 index 0000000..474f666 --- /dev/null +++ b/build-locale-archive.c @@ -0,0 +1,632 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../locale/hashval.h" +#define __LC_LAST 13 +#include "../locale/locarchive.h" +#include "../crypt/md5.h" + +const char *alias_file = DATADIR "/locale/locale.alias"; +const char *locar_file = PREFIX "/lib/locale/locale-archive"; +const char *tmpl_file = PREFIX "/lib/locale/locale-archive.tmpl"; +const char *loc_path = PREFIX "/lib/locale/"; +int be_quiet = 1; +int verbose = 0; +int max_locarchive_open_retry = 10; +const char *output_prefix; + +static const char *locnames[] = + { +#define DEFINE_CATEGORY(category, category_name, items, a) \ + [category] = category_name, +#include "../locale/categories.def" +#undef DEFINE_CATEGORY + }; + +static int +is_prime (unsigned long candidate) +{ + /* No even number and none less than 10 will be passed here. */ + unsigned long int divn = 3; + unsigned long int sq = divn * divn; + + while (sq < candidate && candidate % divn != 0) + { + ++divn; + sq += 4 * divn; + ++divn; + } + + return candidate % divn != 0; +} + +unsigned long +next_prime (unsigned long seed) +{ + /* Make it definitely odd. */ + seed |= 1; + + while (!is_prime (seed)) + seed += 2; + + return seed; +} + +void +error (int status, int errnum, const char *message, ...) +{ + va_list args; + + va_start (args, message); + fflush (stdout); + fprintf (stderr, "%s: ", program_invocation_name); + vfprintf (stderr, message, args); + va_end (args); + if (errnum) + fprintf (stderr, ": %s", strerror (errnum)); + putc ('\n', stderr); + fflush (stderr); + if (status) + exit (errnum == EROFS ? 0 : status); +} + +void * +xmalloc (size_t size) +{ + void *p = malloc (size); + if (p == NULL) + error (EXIT_FAILURE, errno, "could not allocate %zd bytes of memory", size); + return p; +} + +static void +open_tmpl_archive (struct locarhandle *ah) +{ + struct stat64 st; + int fd; + struct locarhead head; + const char *archivefname = tmpl_file; + + /* Open the archive. We must have exclusive write access. */ + fd = open64 (archivefname, O_RDONLY); + if (fd == -1) + error (EXIT_FAILURE, errno, "cannot open locale archive template file \"%s\"", + archivefname); + + if (fstat64 (fd, &st) < 0) + error (EXIT_FAILURE, errno, "cannot stat locale archive template file \"%s\"", + archivefname); + + /* Read the header. */ + if (TEMP_FAILURE_RETRY (read (fd, &head, sizeof (head))) != sizeof (head)) + error (EXIT_FAILURE, errno, "cannot read archive header"); + + ah->fd = fd; + ah->mmaped = (head.sumhash_offset + + head.sumhash_size * sizeof (struct sumhashent)); + if (ah->mmaped > (unsigned long) st.st_size) + error (EXIT_FAILURE, 0, "locale archite template file truncated"); + ah->mmaped = st.st_size; + ah->reserved = st.st_size; + + /* Now we know how large the administrative information part is. + Map all of it. */ + ah->addr = mmap64 (NULL, ah->mmaped, PROT_READ, MAP_SHARED, fd, 0); + if (ah->addr == MAP_FAILED) + error (EXIT_FAILURE, errno, "cannot map archive header"); +} + +/* Open the locale archive. */ +extern void open_archive (struct locarhandle *ah, bool readonly); + +/* Close the locale archive. */ +extern void close_archive (struct locarhandle *ah); + +/* Add given locale data to the archive. */ +extern int add_locale_to_archive (struct locarhandle *ah, const char *name, + locale_data_t data, bool replace); + +extern void add_alias (struct locarhandle *ah, const char *alias, + bool replace, const char *oldname, + uint32_t *locrec_offset_p); + +extern struct namehashent * +insert_name (struct locarhandle *ah, + const char *name, size_t name_len, bool replace); + +struct nameent +{ + char *name; + struct locrecent *locrec; +}; + +struct dataent +{ + const unsigned char *sum; + uint32_t file_offset; +}; + +static int +nameentcmp (const void *a, const void *b) +{ + struct locrecent *la = ((const struct nameent *) a)->locrec; + struct locrecent *lb = ((const struct nameent *) b)->locrec; + uint32_t start_a = -1, end_a = 0; + uint32_t start_b = -1, end_b = 0; + int cnt; + + for (cnt = 0; cnt < __LC_LAST; ++cnt) + if (cnt != LC_ALL) + { + if (la->record[cnt].offset < start_a) + start_a = la->record[cnt].offset; + if (la->record[cnt].offset + la->record[cnt].len > end_a) + end_a = la->record[cnt].offset + la->record[cnt].len; + } + assert (start_a != (uint32_t)-1); + assert (end_a != 0); + + for (cnt = 0; cnt < __LC_LAST; ++cnt) + if (cnt != LC_ALL) + { + if (lb->record[cnt].offset < start_b) + start_b = lb->record[cnt].offset; + if (lb->record[cnt].offset + lb->record[cnt].len > end_b) + end_b = lb->record[cnt].offset + lb->record[cnt].len; + } + assert (start_b != (uint32_t)-1); + assert (end_b != 0); + + if (start_a != start_b) + return (int)start_a - (int)start_b; + return (int)end_a - (int)end_b; +} + +static int +dataentcmp (const void *a, const void *b) +{ + if (((const struct dataent *) a)->file_offset + < ((const struct dataent *) b)->file_offset) + return -1; + + if (((const struct dataent *) a)->file_offset + > ((const struct dataent *) b)->file_offset) + return 1; + + return 0; +} + +static int +sumsearchfn (const void *key, const void *ent) +{ + uint32_t keyn = *(uint32_t *)key; + uint32_t entn = ((struct dataent *)ent)->file_offset; + + if (keyn < entn) + return -1; + if (keyn > entn) + return 1; + return 0; +} + +static void +compute_data (struct locarhandle *ah, struct nameent *name, size_t sumused, + struct dataent *files, locale_data_t data) +{ + int cnt; + struct locrecent *locrec = name->locrec; + struct dataent *file; + data[LC_ALL].addr = ((char *) ah->addr) + locrec->record[LC_ALL].offset; + data[LC_ALL].size = locrec->record[LC_ALL].len; + for (cnt = 0; cnt < __LC_LAST; ++cnt) + if (cnt != LC_ALL) + { + data[cnt].addr = ((char *) ah->addr) + locrec->record[cnt].offset; + data[cnt].size = locrec->record[cnt].len; + if (data[cnt].addr >= data[LC_ALL].addr + && data[cnt].addr + data[cnt].size + <= data[LC_ALL].addr + data[LC_ALL].size) + __md5_buffer (data[cnt].addr, data[cnt].size, data[cnt].sum); + else + { + file = bsearch (&locrec->record[cnt].offset, files, sumused, + sizeof (*files), sumsearchfn); + if (file == NULL) + error (EXIT_FAILURE, 0, "inconsistent template file"); + memcpy (data[cnt].sum, file->sum, sizeof (data[cnt].sum)); + } + } +} + +static int +fill_archive (struct locarhandle *tmpl_ah, size_t nlist, char *list[], + const char *primary) +{ + struct locarhandle ah; + struct locarhead *head; + int result = 0; + struct nameent *names; + struct namehashent *namehashtab; + size_t cnt, used; + struct dataent *files; + struct sumhashent *sumhashtab; + size_t sumused; + struct locrecent *primary_locrec = NULL; + struct nameent *primary_nameent = NULL; + + head = tmpl_ah->addr; + names = (struct nameent *) malloc (head->namehash_used + * sizeof (struct nameent)); + files = (struct dataent *) malloc (head->sumhash_used + * sizeof (struct dataent)); + if (names == NULL || files == NULL) + error (EXIT_FAILURE, errno, "could not allocate tables"); + + namehashtab = (struct namehashent *) ((char *) tmpl_ah->addr + + head->namehash_offset); + sumhashtab = (struct sumhashent *) ((char *) tmpl_ah->addr + + head->sumhash_offset); + + for (cnt = used = 0; cnt < head->namehash_size; ++cnt) + if (namehashtab[cnt].locrec_offset != 0) + { + assert (used < head->namehash_used); + names[used].name = tmpl_ah->addr + namehashtab[cnt].name_offset; + names[used++].locrec + = (struct locrecent *) ((char *) tmpl_ah->addr + + namehashtab[cnt].locrec_offset); + } + + /* Sort the names. */ + qsort (names, used, sizeof (struct nameent), nameentcmp); + + for (cnt = sumused = 0; cnt < head->sumhash_size; ++cnt) + if (sumhashtab[cnt].file_offset != 0) + { + assert (sumused < head->sumhash_used); + files[sumused].sum = (const unsigned char *) sumhashtab[cnt].sum; + files[sumused++].file_offset = sumhashtab[cnt].file_offset; + } + + /* Sort by file locations. */ + qsort (files, sumused, sizeof (struct dataent), dataentcmp); + + /* Open the archive. This call never returns if we cannot + successfully open the archive. */ + open_archive (&ah, false); + + if (primary != NULL) + { + for (cnt = 0; cnt < used; ++cnt) + if (strcmp (names[cnt].name, primary) == 0) + break; + if (cnt < used) + { + locale_data_t data; + + compute_data (tmpl_ah, &names[cnt], sumused, files, data); + result |= add_locale_to_archive (&ah, primary, data, 0); + primary_locrec = names[cnt].locrec; + primary_nameent = &names[cnt]; + } + } + + for (cnt = 0; cnt < used; ++cnt) + if (&names[cnt] == primary_nameent) + continue; + else if ((cnt > 0 && names[cnt - 1].locrec == names[cnt].locrec) + || names[cnt].locrec == primary_locrec) + { + const char *oldname; + struct namehashent *namehashent; + uint32_t locrec_offset; + + if (names[cnt].locrec == primary_locrec) + oldname = primary; + else + oldname = names[cnt - 1].name; + namehashent = insert_name (&ah, oldname, strlen (oldname), true); + assert (namehashent->name_offset != 0); + assert (namehashent->locrec_offset != 0); + locrec_offset = namehashent->locrec_offset; + add_alias (&ah, names[cnt].name, 0, oldname, &locrec_offset); + } + else + { + locale_data_t data; + + compute_data (tmpl_ah, &names[cnt], sumused, files, data); + result |= add_locale_to_archive (&ah, names[cnt].name, data, 0); + } + + while (nlist-- > 0) + { + const char *fname = *list++; + size_t fnamelen = strlen (fname); + struct stat64 st; + DIR *dirp; + struct dirent64 *d; + int seen; + locale_data_t data; + int cnt; + + /* First see whether this really is a directory and whether it + contains all the require locale category files. */ + if (stat64 (fname, &st) < 0) + { + error (0, 0, "stat of \"%s\" failed: %s: ignored", fname, + strerror (errno)); + continue; + } + if (!S_ISDIR (st.st_mode)) + { + error (0, 0, "\"%s\" is no directory; ignored", fname); + continue; + } + + dirp = opendir (fname); + if (dirp == NULL) + { + error (0, 0, "cannot open directory \"%s\": %s: ignored", + fname, strerror (errno)); + continue; + } + + seen = 0; + while ((d = readdir64 (dirp)) != NULL) + { + for (cnt = 0; cnt < __LC_LAST; ++cnt) + if (cnt != LC_ALL) + if (strcmp (d->d_name, locnames[cnt]) == 0) + { + unsigned char d_type; + + /* We have an object of the required name. If it's + a directory we have to look at a file with the + prefix "SYS_". Otherwise we have found what we + are looking for. */ +#ifdef _DIRENT_HAVE_D_TYPE + d_type = d->d_type; + + if (d_type != DT_REG) +#endif + { + char fullname[fnamelen + 2 * strlen (d->d_name) + 7]; + +#ifdef _DIRENT_HAVE_D_TYPE + if (d_type == DT_UNKNOWN) +#endif + { + strcpy (stpcpy (stpcpy (fullname, fname), "/"), + d->d_name); + + if (stat64 (fullname, &st) == -1) + /* We cannot stat the file, ignore it. */ + break; + + d_type = IFTODT (st.st_mode); + } + + if (d_type == DT_DIR) + { + /* We have to do more tests. The file is a + directory and it therefore must contain a + regular file with the same name except a + "SYS_" prefix. */ + char *t = stpcpy (stpcpy (fullname, fname), "/"); + strcpy (stpcpy (stpcpy (t, d->d_name), "/SYS_"), + d->d_name); + + if (stat64 (fullname, &st) == -1) + /* There is no SYS_* file or we cannot + access it. */ + break; + + d_type = IFTODT (st.st_mode); + } + } + + /* If we found a regular file (eventually after + following a symlink) we are successful. */ + if (d_type == DT_REG) + ++seen; + break; + } + } + + closedir (dirp); + + if (seen != __LC_LAST - 1) + { + /* We don't have all locale category files. Ignore the name. */ + error (0, 0, "incomplete set of locale files in \"%s\"", + fname); + continue; + } + + /* Add the files to the archive. To do this we first compute + sizes and the MD5 sums of all the files. */ + for (cnt = 0; cnt < __LC_LAST; ++cnt) + if (cnt != LC_ALL) + { + char fullname[fnamelen + 2 * strlen (locnames[cnt]) + 7]; + int fd; + + strcpy (stpcpy (stpcpy (fullname, fname), "/"), locnames[cnt]); + fd = open64 (fullname, O_RDONLY); + if (fd == -1 || fstat64 (fd, &st) == -1) + { + /* Cannot read the file. */ + if (fd != -1) + close (fd); + break; + } + + if (S_ISDIR (st.st_mode)) + { + char *t; + close (fd); + t = stpcpy (stpcpy (fullname, fname), "/"); + strcpy (stpcpy (stpcpy (t, locnames[cnt]), "/SYS_"), + locnames[cnt]); + + fd = open64 (fullname, O_RDONLY); + if (fd == -1 || fstat64 (fd, &st) == -1 + || !S_ISREG (st.st_mode)) + { + if (fd != -1) + close (fd); + break; + } + } + + /* Map the file. */ + data[cnt].addr = mmap64 (NULL, st.st_size, PROT_READ, MAP_SHARED, + fd, 0); + if (data[cnt].addr == MAP_FAILED) + { + /* Cannot map it. */ + close (fd); + break; + } + + data[cnt].size = st.st_size; + __md5_buffer (data[cnt].addr, st.st_size, data[cnt].sum); + + /* We don't need the file descriptor anymore. */ + close (fd); + } + + if (cnt != __LC_LAST) + { + while (cnt-- > 0) + if (cnt != LC_ALL) + munmap (data[cnt].addr, data[cnt].size); + + error (0, 0, "cannot read all files in \"%s\": ignored", fname); + + continue; + } + + result |= add_locale_to_archive (&ah, basename (fname), data, 0); + + for (cnt = 0; cnt < __LC_LAST; ++cnt) + if (cnt != LC_ALL) + munmap (data[cnt].addr, data[cnt].size); + } + + /* We are done. */ + close_archive (&ah); + + return result; +} + +int main () +{ + char path[4096]; + DIR *dirp; + struct dirent64 *d; + struct stat64 st; + char *list[16384], *primary; + unsigned int cnt = 0; + struct locarhandle tmpl_ah; + size_t loc_path_len = strlen (loc_path); + + dirp = opendir (loc_path); + if (dirp == NULL) + error (EXIT_FAILURE, errno, "cannot open directory \"%s\"", loc_path); + + open_tmpl_archive (&tmpl_ah); + + unlink (locar_file); + primary = getenv ("LC_ALL"); + if (primary == NULL) + primary = getenv ("LANG"); + if (primary != NULL) + { + if (strncmp (primary, "ja", 2) != 0 + && strncmp (primary, "ko", 2) != 0 + && strncmp (primary, "zh", 2) != 0) + { + char *ptr = malloc (strlen (primary) + strlen (".utf8") + 1), *p, *q; + + if (ptr != NULL) + { + p = ptr; + q = primary; + while (*q && *q != '.' && *q != '@') + *p++ = *q++; + if (*q == '.') + while (*q && *q != '@') + q++; + p = stpcpy (p, ".utf8"); + strcpy (p, q); + primary = ptr; + } + else + primary = NULL; + } + } + + memcpy (path, loc_path, loc_path_len); + + while ((d = readdir64 (dirp)) != NULL) + { + if (strcmp (d->d_name, ".") == 0 || strcmp (d->d_name, "..") == 0) + continue; + if (strchr (d->d_name, '_') == NULL) + continue; + + size_t d_name_len = strlen (d->d_name); + if (loc_path_len + d_name_len + 1 > sizeof (path)) + { + error (0, 0, "too long filename \"%s\"", d->d_name); + continue; + } + + memcpy (path + loc_path_len, d->d_name, d_name_len + 1); + if (stat64 (path, &st) < 0) + { + error (0, errno, "cannot stat \"%s\"", path); + continue; + } + if (! S_ISDIR (st.st_mode)) + continue; + if (cnt == 16384) + { + error (0, 0, "too many directories in \"%s\"", loc_path); + break; + } + list[cnt] = strdup (path); + if (list[cnt] == NULL) + { + error (0, errno, "cannot add file to list \"%s\"", path); + continue; + } + if (primary != NULL && cnt > 0 && strcmp (primary, d->d_name) == 0) + { + char *p = list[0]; + list[0] = list[cnt]; + list[cnt] = p; + } + cnt++; + } + closedir (dirp); + fill_archive (&tmpl_ah, cnt, list, primary); + close_archive (&tmpl_ah); + truncate (tmpl_file, 0); + char *argv[] = { "/usr/sbin/tzdata-update", NULL }; + execve (argv[0], (char *const *)argv, (char *const *)&argv[1]); + exit (0); +} diff --git a/glibc-c_stubs.patch b/glibc-c_stubs.patch new file mode 100644 index 0000000..934f0d0 --- /dev/null +++ b/glibc-c_stubs.patch @@ -0,0 +1,754 @@ +diff -pruN glibc-2.17-931-g30bbc0c/c_stubs/Banner glibc-2.17-931-g30bbc0c.new/c_stubs/Banner +--- glibc-2.17-931-g30bbc0c/c_stubs/Banner 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/c_stubs/Banner 2011-10-19 16:34:41.000000000 +0530 +@@ -0,0 +1 @@ ++The C stubs add-on version 2.1.2. +diff -pruN glibc-2.17-931-g30bbc0c/c_stubs/ChangeLog glibc-2.17-931-g30bbc0c.new/c_stubs/ChangeLog +--- glibc-2.17-931-g30bbc0c/c_stubs/ChangeLog 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/c_stubs/ChangeLog 2011-10-19 16:34:41.000000000 +0530 +@@ -0,0 +1,46 @@ ++2006-03-01 Jakub Jelinek ++ ++ * configure (libc_add_on_canonical, libc_add_on_subdir): Set. ++ ++2001-08-07 Jakub Jelinek ++ ++ * gconv_stubs.c (__gconv_lookup_alias): Remove. ++ (__gconv_NOOP, __gconv_compare_alias, __gconv_release_cache, ++ __gconv_release_step): New. ++ ++2001-06-07 Jakub Jelinek ++ ++ * gconv_stubs.c (__gconv_lookup_alias): New. ++ ++2000-02-27 Cristian Gafton ++ ++ * gconv_stubs.c: Return __gconv_OK for: ++ __gconv_transform_ascii_internal ++ __gconv_transform_ucs2little_internal ++ __gconv_transform_utf16_internal ++ __gconv_transform_utf8_internal ++ __gconv_transform_ucs2_internal ++ ++2000-02-25 Cristian Gafton ++ ++ * gconv_stubs.c: add __c_stubs_is_compiled_in so we can detect when ++ the library is linked in. ++ ++Wed Dec 8 13:47:25 1999 Ivan Brunello ++ ++ * Makefile (extra-objs): Changed stubs.o to gconv_stubs.o. ++ ++Sun Dec 5 11:32:17 1999 H.J. Lu ++ ++ * gconv_stubs.c: Renamed from stubs.c. ++ Support glibc 2.1.x. ++ ++Mon Aug 23 16:42:05 1999 H.J. Lu ++ ++ * Banner: New. ++ * COPYING.LIB: Likewise. ++ * Makefile: Likewise. ++ * README: Likewise. ++ * configure: Likewise. ++ * stubs.c: Likewise. ++ * test-stdio.c: Likewise. +diff -pruN glibc-2.17-931-g30bbc0c/c_stubs/configure glibc-2.17-931-g30bbc0c.new/c_stubs/configure +--- glibc-2.17-931-g30bbc0c/c_stubs/configure 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/c_stubs/configure 2013-08-16 16:26:11.637020805 +0530 +@@ -0,0 +1,5 @@ ++# This is only to keep the GNU C library configure mechanism happy. ++# This is a shell script fragment sourced by the main configure script. ++ ++libc_add_on_canonical= ++libc_add_on_subdirs=. +diff -pruN glibc-2.17-931-g30bbc0c/c_stubs/COPYING.LIB glibc-2.17-931-g30bbc0c.new/c_stubs/COPYING.LIB +--- glibc-2.17-931-g30bbc0c/c_stubs/COPYING.LIB 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/c_stubs/COPYING.LIB 2011-10-19 16:34:41.000000000 +0530 +@@ -0,0 +1,482 @@ ++ GNU LIBRARY GENERAL PUBLIC LICENSE ++ Version 2, June 1991 ++ ++ Copyright (C) 1991 Free Software Foundation, Inc. ++ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA ++ Everyone is permitted to copy and distribute verbatim copies ++ of this license document, but changing it is not allowed. ++ ++[This is the first released version of the library GPL. It is ++ numbered 2 because it goes with version 2 of the ordinary GPL.] ++ ++ Preamble ++ ++ The licenses for most software are designed to take away your ++freedom to share and change it. By contrast, the GNU General Public ++Licenses are intended to guarantee your freedom to share and change ++free software--to make sure the software is free for all its users. ++ ++ This license, the Library General Public License, applies to some ++specially designated Free Software Foundation software, and to any ++other libraries whose authors decide to use it. You can use it for ++your libraries, too. ++ ++ When we speak of free software, we are referring to freedom, not ++price. Our General Public Licenses are designed to make sure that you ++have the freedom to distribute copies of free software (and charge for ++this service if you wish), that you receive source code or can get it ++if you want it, that you can change the software or use pieces of it ++in new free programs; and that you know you can do these things. ++ ++ To protect your rights, we need to make restrictions that forbid ++anyone to deny you these rights or to ask you to surrender the rights. ++These restrictions translate to certain responsibilities for you if ++you distribute copies of the library, or if you modify it. ++ ++ For example, if you distribute copies of the library, whether gratis ++or for a fee, you must give the recipients all the rights that we gave ++you. You must make sure that they, too, receive or can get the source ++code. If you link a program with the library, you must provide ++complete object files to the recipients so that they can relink them ++with the library, after making changes to the library and recompiling ++it. And you must show them these terms so they know their rights. ++ ++ Our method of protecting your rights has two steps: (1) copyright ++the library, and (2) offer you this license which gives you legal ++permission to copy, distribute and/or modify the library. ++ ++ Also, for each distributor's protection, we want to make certain ++that everyone understands that there is no warranty for this free ++library. If the library is modified by someone else and passed on, we ++want its recipients to know that what they have is not the original ++version, so that any problems introduced by others will not reflect on ++the original authors' reputations. ++ ++ Finally, any free program is threatened constantly by software ++patents. We wish to avoid the danger that companies distributing free ++software will individually obtain patent licenses, thus in effect ++transforming the program into proprietary software. To prevent this, ++we have made it clear that any patent must be licensed for everyone's ++free use or not licensed at all. ++ ++ Most GNU software, including some libraries, is covered by the ordinary ++GNU General Public License, which was designed for utility programs. This ++license, the GNU Library General Public License, applies to certain ++designated libraries. This license is quite different from the ordinary ++one; be sure to read it in full, and don't assume that anything in it is ++the same as in the ordinary license. ++ ++ The reason we have a separate public license for some libraries is that ++they blur the distinction we usually make between modifying or adding to a ++program and simply using it. Linking a program with a library, without ++changing the library, is in some sense simply using the library, and is ++analogous to running a utility program or application program. However, in ++a textual and legal sense, the linked executable is a combined work, a ++derivative of the original library, and the ordinary General Public License ++treats it as such. ++ ++ Because of this blurred distinction, using the ordinary General ++Public License for libraries did not effectively promote software ++sharing, because most developers did not use the libraries. We ++concluded that weaker conditions might promote sharing better. ++ ++ However, unrestricted linking of non-free programs would deprive the ++users of those programs of all benefit from the free status of the ++libraries themselves. This Library General Public License is intended to ++permit developers of non-free programs to use free libraries, while ++preserving your freedom as a user of such programs to change the free ++libraries that are incorporated in them. (We have not seen how to achieve ++this as regards changes in header files, but we have achieved it as regards ++changes in the actual functions of the Library.) The hope is that this ++will lead to faster development of free libraries. ++ ++ The precise terms and conditions for copying, distribution and ++modification follow. Pay close attention to the difference between a ++"work based on the library" and a "work that uses the library". The ++former contains code derived from the library, while the latter only ++works together with the library. ++ ++ Note that it is possible for a library to be covered by the ordinary ++General Public License rather than by this special one. ++ ++ GNU LIBRARY GENERAL PUBLIC LICENSE ++ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION ++ ++ 0. This License Agreement applies to any software library which ++contains a notice placed by the copyright holder or other authorized ++party saying it may be distributed under the terms of this Library ++General Public License (also called "this License"). Each licensee is ++addressed as "you". ++ ++ A "library" means a collection of software functions and/or data ++prepared so as to be conveniently linked with application programs ++(which use some of those functions and data) to form executables. ++ ++ The "Library", below, refers to any such software library or work ++which has been distributed under these terms. A "work based on the ++Library" means either the Library or any derivative work under ++copyright law: that is to say, a work containing the Library or a ++portion of it, either verbatim or with modifications and/or translated ++straightforwardly into another language. (Hereinafter, translation is ++included without limitation in the term "modification".) ++ ++ "Source code" for a work means the preferred form of the work for ++making modifications to it. For a library, complete source code means ++all the source code for all modules it contains, plus any associated ++interface definition files, plus the scripts used to control compilation ++and installation of the library. ++ ++ Activities other than copying, distribution and modification are not ++covered by this License; they are outside its scope. The act of ++running a program using the Library is not restricted, and output from ++such a program is covered only if its contents constitute a work based ++on the Library (independent of the use of the Library in a tool for ++writing it). Whether that is true depends on what the Library does ++and what the program that uses the Library does. ++ ++ 1. You may copy and distribute verbatim copies of the Library's ++complete source code as you receive it, in any medium, provided that ++you conspicuously and appropriately publish on each copy an ++appropriate copyright notice and disclaimer of warranty; keep intact ++all the notices that refer to this License and to the absence of any ++warranty; and distribute a copy of this License along with the ++Library. ++ ++ You may charge a fee for the physical act of transferring a copy, ++and you may at your option offer warranty protection in exchange for a ++fee. ++ ++ 2. You may modify your copy or copies of the Library or any portion ++of it, thus forming a work based on the Library, and copy and ++distribute such modifications or work under the terms of Section 1 ++above, provided that you also meet all of these conditions: ++ ++ a) The modified work must itself be a software library. ++ ++ b) You must cause the files modified to carry prominent notices ++ stating that you changed the files and the date of any change. ++ ++ c) You must cause the whole of the work to be licensed at no ++ charge to all third parties under the terms of this License. ++ ++ d) If a facility in the modified Library refers to a function or a ++ table of data to be supplied by an application program that uses ++ the facility, other than as an argument passed when the facility ++ is invoked, then you must make a good faith effort to ensure that, ++ in the event an application does not supply such function or ++ table, the facility still operates, and performs whatever part of ++ its purpose remains meaningful. ++ ++ (For example, a function in a library to compute square roots has ++ a purpose that is entirely well-defined independent of the ++ application. Therefore, Subsection 2d requires that any ++ application-supplied function or table used by this function must ++ be optional: if the application does not supply it, the square ++ root function must still compute square roots.) ++ ++These requirements apply to the modified work as a whole. If ++identifiable sections of that work are not derived from the Library, ++and can be reasonably considered independent and separate works in ++themselves, then this License, and its terms, do not apply to those ++sections when you distribute them as separate works. But when you ++distribute the same sections as part of a whole which is a work based ++on the Library, the distribution of the whole must be on the terms of ++this License, whose permissions for other licensees extend to the ++entire whole, and thus to each and every part regardless of who wrote ++it. ++ ++Thus, it is not the intent of this section to claim rights or contest ++your rights to work written entirely by you; rather, the intent is to ++exercise the right to control the distribution of derivative or ++collective works based on the Library. ++ ++In addition, mere aggregation of another work not based on the Library ++with the Library (or with a work based on the Library) on a volume of ++a storage or distribution medium does not bring the other work under ++the scope of this License. ++ ++ 3. You may opt to apply the terms of the ordinary GNU General Public ++License instead of this License to a given copy of the Library. To do ++this, you must alter all the notices that refer to this License, so ++that they refer to the ordinary GNU General Public License, version 2, ++instead of to this License. (If a newer version than version 2 of the ++ordinary GNU General Public License has appeared, then you can specify ++that version instead if you wish.) Do not make any other change in ++these notices. ++ ++ Once this change is made in a given copy, it is irreversible for ++that copy, so the ordinary GNU General Public License applies to all ++subsequent copies and derivative works made from that copy. ++ ++ This option is useful when you wish to copy part of the code of ++the Library into a program that is not a library. ++ ++ 4. You may copy and distribute the Library (or a portion or ++derivative of it, under Section 2) in object code or executable form ++under the terms of Sections 1 and 2 above provided that you accompany ++it with the complete corresponding machine-readable source code, which ++must be distributed under the terms of Sections 1 and 2 above on a ++medium customarily used for software interchange. ++ ++ If distribution of object code is made by offering access to copy ++from a designated place, then offering equivalent access to copy the ++source code from the same place satisfies the requirement to ++distribute the source code, even though third parties are not ++compelled to copy the source along with the object code. ++ ++ 5. A program that contains no derivative of any portion of the ++Library, but is designed to work with the Library by being compiled or ++linked with it, is called a "work that uses the Library". Such a ++work, in isolation, is not a derivative work of the Library, and ++therefore falls outside the scope of this License. ++ ++ However, linking a "work that uses the Library" with the Library ++creates an executable that is a derivative of the Library (because it ++contains portions of the Library), rather than a "work that uses the ++library". The executable is therefore covered by this License. ++Section 6 states terms for distribution of such executables. ++ ++ When a "work that uses the Library" uses material from a header file ++that is part of the Library, the object code for the work may be a ++derivative work of the Library even though the source code is not. ++Whether this is true is especially significant if the work can be ++linked without the Library, or if the work is itself a library. The ++threshold for this to be true is not precisely defined by law. ++ ++ If such an object file uses only numerical parameters, data ++structure layouts and accessors, and small macros and small inline ++functions (ten lines or less in length), then the use of the object ++file is unrestricted, regardless of whether it is legally a derivative ++work. (Executables containing this object code plus portions of the ++Library will still fall under Section 6.) ++ ++ Otherwise, if the work is a derivative of the Library, you may ++distribute the object code for the work under the terms of Section 6. ++Any executables containing that work also fall under Section 6, ++whether or not they are linked directly with the Library itself. ++ ++ 6. As an exception to the Sections above, you may also compile or ++link a "work that uses the Library" with the Library to produce a ++work containing portions of the Library, and distribute that work ++under terms of your choice, provided that the terms permit ++modification of the work for the customer's own use and reverse ++engineering for debugging such modifications. ++ ++ You must give prominent notice with each copy of the work that the ++Library is used in it and that the Library and its use are covered by ++this License. You must supply a copy of this License. If the work ++during execution displays copyright notices, you must include the ++copyright notice for the Library among them, as well as a reference ++directing the user to the copy of this License. Also, you must do one ++of these things: ++ ++ a) Accompany the work with the complete corresponding ++ machine-readable source code for the Library including whatever ++ changes were used in the work (which must be distributed under ++ Sections 1 and 2 above); and, if the work is an executable linked ++ with the Library, with the complete machine-readable "work that ++ uses the Library", as object code and/or source code, so that the ++ user can modify the Library and then relink to produce a modified ++ executable containing the modified Library. (It is understood ++ that the user who changes the contents of definitions files in the ++ Library will not necessarily be able to recompile the application ++ to use the modified definitions.) ++ ++ b) Accompany the work with a written offer, valid for at ++ least three years, to give the same user the materials ++ specified in Subsection 6a, above, for a charge no more ++ than the cost of performing this distribution. ++ ++ c) If distribution of the work is made by offering access to copy ++ from a designated place, offer equivalent access to copy the above ++ specified materials from the same place. ++ ++ d) Verify that the user has already received a copy of these ++ materials or that you have already sent this user a copy. ++ ++ For an executable, the required form of the "work that uses the ++Library" must include any data and utility programs needed for ++reproducing the executable from it. However, as a special exception, ++the source code distributed need not include anything that is normally ++distributed (in either source or binary form) with the major ++components (compiler, kernel, and so on) of the operating system on ++which the executable runs, unless that component itself accompanies ++the executable. ++ ++ It may happen that this requirement contradicts the license ++restrictions of other proprietary libraries that do not normally ++accompany the operating system. Such a contradiction means you cannot ++use both them and the Library together in an executable that you ++distribute. ++ ++ 7. You may place library facilities that are a work based on the ++Library side-by-side in a single library together with other library ++facilities not covered by this License, and distribute such a combined ++library, provided that the separate distribution of the work based on ++the Library and of the other library facilities is otherwise ++permitted, and provided that you do these two things: ++ ++ a) Accompany the combined library with a copy of the same work ++ based on the Library, uncombined with any other library ++ facilities. This must be distributed under the terms of the ++ Sections above. ++ ++ b) Give prominent notice with the combined library of the fact ++ that part of it is a work based on the Library, and explaining ++ where to find the accompanying uncombined form of the same work. ++ ++ 8. You may not copy, modify, sublicense, link with, or distribute ++the Library except as expressly provided under this License. Any ++attempt otherwise to copy, modify, sublicense, link with, or ++distribute the Library is void, and will automatically terminate your ++rights under this License. However, parties who have received copies, ++or rights, from you under this License will not have their licenses ++terminated so long as such parties remain in full compliance. ++ ++ 9. You are not required to accept this License, since you have not ++signed it. However, nothing else grants you permission to modify or ++distribute the Library or its derivative works. These actions are ++prohibited by law if you do not accept this License. Therefore, by ++modifying or distributing the Library (or any work based on the ++Library), you indicate your acceptance of this License to do so, and ++all its terms and conditions for copying, distributing or modifying ++the Library or works based on it. ++ ++ 10. Each time you redistribute the Library (or any work based on the ++Library), the recipient automatically receives a license from the ++original licensor to copy, distribute, link with or modify the Library ++subject to these terms and conditions. You may not impose any further ++restrictions on the recipients' exercise of the rights granted herein. ++You are not responsible for enforcing compliance by third parties to ++this License. ++ ++ 11. If, as a consequence of a court judgment or allegation of patent ++infringement or for any other reason (not limited to patent issues), ++conditions are imposed on you (whether by court order, agreement or ++otherwise) that contradict the conditions of this License, they do not ++excuse you from the conditions of this License. If you cannot ++distribute so as to satisfy simultaneously your obligations under this ++License and any other pertinent obligations, then as a consequence you ++may not distribute the Library at all. For example, if a patent ++license would not permit royalty-free redistribution of the Library by ++all those who receive copies directly or indirectly through you, then ++the only way you could satisfy both it and this License would be to ++refrain entirely from distribution of the Library. ++ ++If any portion of this section is held invalid or unenforceable under any ++particular circumstance, the balance of the section is intended to apply, ++and the section as a whole is intended to apply in other circumstances. ++ ++It is not the purpose of this section to induce you to infringe any ++patents or other property right claims or to contest validity of any ++such claims; this section has the sole purpose of protecting the ++integrity of the free software distribution system which is ++implemented by public license practices. Many people have made ++generous contributions to the wide range of software distributed ++through that system in reliance on consistent application of that ++system; it is up to the author/donor to decide if he or she is willing ++to distribute software through any other system and a licensee cannot ++impose that choice. ++ ++This section is intended to make thoroughly clear what is believed to ++be a consequence of the rest of this License. ++ ++ 12. If the distribution and/or use of the Library is restricted in ++certain countries either by patents or by copyrighted interfaces, the ++original copyright holder who places the Library under this License may add ++an explicit geographical distribution limitation excluding those countries, ++so that distribution is permitted only in or among countries not thus ++excluded. In such case, this License incorporates the limitation as if ++written in the body of this License. ++ ++ 13. The Free Software Foundation may publish revised and/or new ++versions of the Library General Public License from time to time. ++Such new versions will be similar in spirit to the present version, ++but may differ in detail to address new problems or concerns. ++ ++Each version is given a distinguishing version number. If the Library ++specifies a version number of this License which applies to it and ++"any later version", you have the option of following the terms and ++conditions either of that version or of any later version published by ++the Free Software Foundation. If the Library does not specify a ++license version number, you may choose any version ever published by ++the Free Software Foundation. ++ ++ 14. If you wish to incorporate parts of the Library into other free ++programs whose distribution conditions are incompatible with these, ++write to the author to ask for permission. For software which is ++copyrighted by the Free Software Foundation, write to the Free ++Software Foundation; we sometimes make exceptions for this. Our ++decision will be guided by the two goals of preserving the free status ++of all derivatives of our free software and of promoting the sharing ++and reuse of software generally. ++ ++ NO WARRANTY ++ ++ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO ++WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. ++EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR ++OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY ++KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE ++IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE ++LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME ++THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. ++ ++ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN ++WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY ++AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU ++FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR ++CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE ++LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING ++RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A ++FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF ++SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH ++DAMAGES. ++ ++ END OF TERMS AND CONDITIONS ++ ++ Appendix: How to Apply These Terms to Your New Libraries ++ ++ If you develop a new library, and you want it to be of the greatest ++possible use to the public, we recommend making it free software that ++everyone can redistribute and change. You can do so by permitting ++redistribution under these terms (or, alternatively, under the terms of the ++ordinary General Public License). ++ ++ To apply these terms, attach the following notices to the library. It is ++safest to attach them to the start of each source file to most effectively ++convey the exclusion of warranty; and each file should have at least the ++"copyright" line and a pointer to where the full notice is found. ++ ++ ++ Copyright (C) ++ ++ This library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Library General Public ++ License as published by the Free Software Foundation; either ++ version 2 of the License, or (at your option) any later version. ++ ++ This 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 ++ Library General Public License for more details. ++ ++ You should have received a copy of the GNU Library General Public ++ License along with this library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, ++ MA 02111-1307, USA ++ ++Also add information on how to contact you by electronic and paper mail. ++ ++You should also get your employer (if you work as a programmer) or your ++school, if any, to sign a "copyright disclaimer" for the library, if ++necessary. Here is a sample; alter the names: ++ ++ Yoyodyne, Inc., hereby disclaims all copyright interest in the ++ library `Frob' (a library for tweaking knobs) written by James Random Hacker. ++ ++ , 1 April 1990 ++ Ty Coon, President of Vice ++ ++That's all there is to it! +diff -pruN glibc-2.17-931-g30bbc0c/c_stubs/gconv_stubs.c glibc-2.17-931-g30bbc0c.new/c_stubs/gconv_stubs.c +--- glibc-2.17-931-g30bbc0c/c_stubs/gconv_stubs.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/c_stubs/gconv_stubs.c 2011-10-19 16:34:41.000000000 +0530 +@@ -0,0 +1,126 @@ ++/* Provide gconv stub functions for the minimum static binaries. ++ Copyright (C) 1999, 2001, 2003, 2004 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 Library General Public License as ++ published by the Free Software Foundation; either version 2 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 ++ Library General Public License for more details. ++ ++ You should have received a copy of the GNU Library General Public ++ License along with the GNU C Library; see the file COPYING.LIB. If not, ++ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ Boston, MA 02111-1307, USA. */ ++ ++#include ++#include ++#include ++#include ++#if __GNUC_PREREQ(3, 3) ++# include ++#else ++# include ++#endif ++ ++__libc_lock_define_initialized (, __gconv_lock) ++ ++/* hack for self identification */ ++int __c_stubs_is_compiled_in; ++ ++/* Don't drag in the dynamic linker. */ ++void *__libc_stack_end; ++ ++int attribute_hidden ++__gconv_OK (void) ++{ ++#if __GLIBC__ > 2 || __GLIBC_MINOR__ > 1 ++ return __GCONV_OK; ++#else ++ return GCONV_OK; ++#endif ++} ++ ++int attribute_hidden ++__gconv_NOCONV (void) ++{ ++#if __GLIBC__ > 2 || __GLIBC_MINOR__ > 1 ++ return __GCONV_NOCONV; ++#else ++ return GCONV_NOCONV; ++#endif ++} ++ ++void attribute_hidden ++__gconv_NOOP (void) ++{ ++} ++ ++int ++internal_function ++__gconv_compare_alias (const char *name1, const char *name2) ++{ ++ return strcmp (name1, name2); ++} ++ ++wint_t ++__gconv_btwoc_ascii (struct __gconv_step *step, unsigned char c) ++{ ++ if (c < 0x80) ++ return c; ++ else ++ return WEOF; ++} ++ ++ ++#if __GNUC_PREREQ(3, 3) ++# undef strong_alias ++# define strong_alias(impl, name) \ ++ __typeof (name) name __attribute__ ((alias (#impl))) ++#endif ++ ++strong_alias (__gconv_OK, ++ __gconv_close_transform); ++strong_alias (__gconv_OK, ++ __gconv_close); ++ ++strong_alias (__gconv_NOCONV, ++ __gconv); ++strong_alias (__gconv_NOCONV, ++ __gconv_find_transform); ++strong_alias (__gconv_NOCONV, ++ __gconv_open); ++ ++/* These transformations should not fail in normal conditions */ ++strong_alias (__gconv_OK, ++ __gconv_transform_ascii_internal); ++strong_alias (__gconv_OK, ++ __gconv_transform_utf16_internal); ++strong_alias (__gconv_OK, ++ __gconv_transform_utf8_internal); ++strong_alias (__gconv_OK, ++ __gconv_transform_ucs2_internal); ++ ++/* We can assume no conversion for these ones */ ++strong_alias (__gconv_NOCONV, ++ __gconv_transform_internal_ascii); ++strong_alias (__gconv_NOCONV, ++ __gconv_transform_internal_ucs2); ++strong_alias (__gconv_NOCONV, ++ __gconv_transform_internal_ucs4); ++strong_alias (__gconv_NOCONV, ++ __gconv_transform_internal_utf16); ++strong_alias (__gconv_NOCONV, ++ __gconv_transform_internal_utf8); ++ ++strong_alias (__gconv_NOCONV, ++ __gconv_transliterate); ++ ++strong_alias (__gconv_NOOP, ++ __gconv_release_cache); ++strong_alias (__gconv_NOOP, ++ __gconv_release_step); +diff -pruN glibc-2.17-931-g30bbc0c/c_stubs/Makefile glibc-2.17-931-g30bbc0c.new/c_stubs/Makefile +--- glibc-2.17-931-g30bbc0c/c_stubs/Makefile 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/c_stubs/Makefile 2011-10-19 16:34:41.000000000 +0530 +@@ -0,0 +1,46 @@ ++# Copyright (C) 1999 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 Library General Public License as ++# published by the Free Software Foundation; either version 2 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 ++# Library General Public License for more details. ++ ++# You should have received a copy of the GNU Library General Public ++# License along with the GNU C Library; see the file COPYING.LIB. If not, ++# write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++# Boston, MA 02111-1307, USA. ++ ++# ++# Sub-makefile for the C stub add-on library. ++# ++subdir := c_stubs ++ ++tests-static := test-stdio ++tests := $(tests-static) ++ ++libc_stubs-objs := gconv_stubs.o ++ ++install-lib := libc_stubs.a ++non-lib.a := libc_stubs.a ++ ++extra-objs := gconv_stubs.o libc_stubs.a ++ ++include ../Makeconfig ++ ++CPPFLAGS += -I../iconv ++ ++include ../Rules ++ ++$(objpfx)libc_stubs.a: $(addprefix $(objpfx), $(libc_stubs-objs)) ++ -rm -f $@ ++ $(CC) -nostdlib -nostartfiles -r -o $@ $^ ++ ++lib: $(objpfx)libc_stubs.a ++ ++$(objpfx)test-stdio: $(objpfx)libc_stubs.a +diff -pruN glibc-2.17-931-g30bbc0c/c_stubs/README glibc-2.17-931-g30bbc0c.new/c_stubs/README +--- glibc-2.17-931-g30bbc0c/c_stubs/README 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/c_stubs/README 2011-10-19 16:34:41.000000000 +0530 +@@ -0,0 +1,8 @@ ++This is a stub add-on library for the GNU C library version 2.1.2 and ++above. It is used to create the smaller static binaries by stubbing ++out the gconv related functions. The resulting binaries may not have ++all the functionalities. ++ ++H.J. Lu ++hjl@gnu.org ++12/05/1999 +diff -pruN glibc-2.17-931-g30bbc0c/c_stubs/test-stdio.c glibc-2.17-931-g30bbc0c.new/c_stubs/test-stdio.c +--- glibc-2.17-931-g30bbc0c/c_stubs/test-stdio.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/c_stubs/test-stdio.c 2011-10-19 16:34:41.000000000 +0530 +@@ -0,0 +1,8 @@ ++#include ++ ++int ++main (void) ++{ ++ printf ("Hello world\n"); ++ return 0; ++} diff --git a/glibc-rtkaio.patch b/glibc-rtkaio.patch new file mode 100644 index 0000000..d7f3d6e --- /dev/null +++ b/glibc-rtkaio.patch @@ -0,0 +1,5000 @@ +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/Banner glibc-2.17-931-g30bbc0c.new/rtkaio/Banner +--- glibc-2.17-931-g30bbc0c/rtkaio/Banner 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/Banner 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++RT using linux kernel aio +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/ChangeLog glibc-2.17-931-g30bbc0c.new/rtkaio/ChangeLog +--- glibc-2.17-931-g30bbc0c/rtkaio/ChangeLog 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/ChangeLog 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1,255 @@ ++2009-10-30 Andreas Schwab ++ ++ * tst-aiod.h: Include . ++ ++2009-09-30 Andreas Schwab ++ ++ * sysdeps/unix/sysv/linux/x86_64/librtkaio-cancellation.S: New ++ file. ++ ++2007-12-12 Jakub Jelinek ++ ++ * sysdeps/unix/sysv/linux/kaio_read.c (aio_read64): Define to ++ something else while including kaio_misc.h. ++ * sysdeps/unix/sysv/linux/kaio_write.c (aio_write64): Likewise. ++ ++2007-08-01 Jakub Jelinek ++ ++ * sysdeps/unix/sysv/linux/kaio_misc.h (AIO_MISC_NOTIFY, ++ AIO_MISC_WAIT): Add LLL_PRIVATE as last argument to lll_futex_*wait. ++ ++2006-09-15 Jakub Jelinek ++ ++ [BZ #3138] ++ * rt/tst-aiod.c (do_prepare): Give name_len type size_t. ++ * rt/tst-aiod64.c (do_prepare): Likewise. ++ ++2006-09-07 Jakub Jelinek ++ ++ * tst-aiod2.c: Adjust test for new semantics of lio_listio. ++ * tst-aiod3.c: The thread is now supposed to be created. ++ ++ * Makefile: Use $(..) in place of ../. ++ (tests): Add tst-aio{8,9,10}, tst-cpuclock{1,2}, tst-cputimer{1,2,3} ++ and tst-clock2. ++ (CPPFLAGS-librtkaio): Append -I$(..)rt. ++ * Versions.def (librtkaio): Add GLIBC_2.4 version. ++ * sysdeps/unix/sysv/linux/kaio_misc.c (wait_for_kernel_requests) ++ [!DONT_NEED_AIO_MISC_COND]: Don't use condvar, use AIO_MISC_WAIT. ++ * sysdeps/unix/sysv/linux/kaio_misc.h [HAVE_FORCED_UNWIND] ++ (DONT_NEED_AIO_MISC_COND, AIO_MISC_NOTIFY, AIO_MISC_WAIT): Define. ++ (struct waitlist) [DONT_NEED_AIO_MISC_COND]: Remove cond. ++ * sysdeps/unix/sysv/linux/kaio_suspend.c (struct clparam) ++ [DONT_NEED_AIO_MISC_COND]: Remove cond. ++ (cleanup) [DONT_NEED_AIO_MISC_COND]: Lock __aio_requests_mutex on ++ entry. Don't destroy param->cond. ++ (aio_suspend): Fail if nent is negative. ++ (aio_suspend) [DONT_NEED_AIO_MISC_COND]: Don't use cond, use ++ AIO_MISC_WAIT. ++ * sysdeps/unix/sysv/linux/klio_listio.c (lio_listio): Renamed to... ++ (lio_listio_internal): ... this. Don't use cond, but AIO_MISC_WAIT, ++ if DONT_NEED_AIO_MISC_COND. Remove mode parameter check. Only set ++ sigevent type to SIGEV_NONE if LIO_NO_INDIVIDUAL_EVENT is set. ++ (__lio_listio_21): New function. Compatiblity version which sets ++ LIO_NO_INDIVIDUAL_EVENT before calling lio_listio_internal. ++ (__lio_listio_item_notify): New function. ++ * sysdeps/unix/sysv/linux/klio_listio64.c: Define __lio_listio_21 and ++ __lio_listio_item_notify macros. ++ * aio.h: Removed. ++ * configure.in: New file ++ * configure: Regenerated. ++ * sysdeps/rtkaio/kaio_cancel.c: Moved to... ++ * kaio_cancel.c: ... here. New file. ++ * sysdeps/rtkaio/kaio_error.c: Moved to... ++ * kaio_error.c: ... here. New file. ++ * sysdeps/rtkaio/kaio_fsync.c: Moved to... ++ * kaio_fsync.c: ... here. New file. ++ * sysdeps/rtkaio/kaio_misc.c: Moved to... ++ * kaio_misc.c: ... here. New file. ++ * sysdeps/rtkaio/kaio_notify.c: Moved to... ++ * kaio_notify.c: ... here. New file. ++ * sysdeps/rtkaio/kaio_read.c: Moved to... ++ * kaio_read.c: ... here. New file. ++ * sysdeps/rtkaio/kaio_read64.c: Moved to... ++ * kaio_read64.c: ... here. New file. ++ * sysdeps/rtkaio/kaio_return.c: Moved to... ++ * kaio_return.c: ... here. New file. ++ * sysdeps/rtkaio/kaio_sigqueue.c: Moved to... ++ * kaio_sigqueue.c: ... here. New file. ++ * sysdeps/rtkaio/kaio_suspend.c: Moved to... ++ * kaio_suspend.c: ... here. New file. ++ * sysdeps/rtkaio/kaio_write.c: Moved to... ++ * kaio_write.c: ... here. New file. ++ * sysdeps/rtkaio/kaio_write64.c: Moved to... ++ * kaio_write64.c: ... here. New file. ++ * sysdeps/rtkaio/klio_listio.c: Moved to... ++ * klio_listio.c: ... here. New file. ++ * sysdeps/rtkaio/klio_listio64.c: Moved to... ++ * klio_listio64.c: ... here. New file. ++ * sysdeps/pthread/Versions: New file. ++ * tst-aio8.c: New file. ++ * tst-aio9.c: New file. ++ * tst-aio10.c: New file. ++ * tst-clock2.c: New file. ++ * tst-cpuclock1.c: New file. ++ * tst-cpuclock2.c: New file. ++ * tst-cputimer1.c: New file. ++ * tst-cputimer2.c: New file. ++ * tst-cputimer3.c: New file. ++ * sysdeps/unix/sysv/linux/sparc/Makefile: New file. ++ * sysdeps/unix/sysv/linux/sparc/rtkaio-sysdep.c: New file. ++ * sysdeps/unix/sysv/linux/sparc/sparc64/Versions: New file. ++ * sysdeps/mips/Makefile: Removed. ++ * sysdeps/unix/mips/rtkaio-sysdep.S: Removed. ++ * sysdeps/unix/sysv/linux/hppa/Versions: Removed. ++ * sysdeps/unix/sysv/linux/hppa/kaio_cancel.c: Removed. ++ ++2006-07-19 Jakub Jelinek ++ ++ * sysdeps/unix/sysv/linux/kaio_misc.c: Include atomic.h. ++ (kernel_callback): Ensure __return_value is updated before ++ __error_code is set. ++ ++2006-05-11 Jakub Jelinek ++ ++ * Makefile (tests): Add tst-mqueue{8,9}, tst-timer5 and ++ tst-aiod{,64,2,3,4,5}. ++ (LDFLAGS-rtkaio.so): Add -Wl,--enable-new-dtags,-z,nodelete. ++ * sysdeps/unix/sysv/linux/kaio_misc.h: Include signal.h and ++ sysdep.h. ++ (aio_start_notify_thread, aio_create_helper_thread): Define ++ for !BROKEN_THREAD_SIGNALS. ++ (__aio_start_notify_thread, __aio_create_helper_thread): New ++ functions for !BROKEN_THREAD_SIGNALS. ++ * sysdeps/unix/sysv/linux/kaio_misc.c: Include sys/sysmacros.h. ++ (aio_create_helper_thread): Define if not yet defined. ++ (__aio_create_helper_thread): New function. ++ (__aio_wait_for_events): Pass 1 rather than 0 as min_nr to ++ io_getevents. ++ (handle_kernel_aio): Likewise. ++ (__aio_create_kernel_thread): Use aio_create_helper_thread. ++ (__aio_enqueue_user_request): Likewise. ++ (handle_fildes_io): Likewise. Remove noreturn attribute, ++ return NULL instead of calling pthread_exit (NULL). ++ (__aio_enqueue_request_ctx): Call fcntl and fxstat64 to avoid using ++ kaio on non-O_DIRECT non-/dev/raw* filedescriptors. For LIO_SYNC ++ and LIO_DSYNC also set kctx to KCTX_NONE. ++ * sysdeps/unix/sysv/linux/kaio_suspend.c (aio_suspend): Don't start ++ handle_kernel_aio thread if ktotal is zero. ++ * sysdeps/pthread/Makefile (tests): Add tst-mqueue8x. ++ (CFLAGS-tst-mqueue8x.c): Add -fexceptions. ++ * Versions.def (librtkaio): Add GLIBC_2.3.4 version. ++ * kaio_mq_close.c: New file. ++ * kaio_mq_getattr.c: New file. ++ * kaio_mq_notify.c: New file. ++ * kaio_mq_open.c: New file. ++ * kaio_mq_receive.c: New file. ++ * kaio_mq_send.c: New file. ++ * kaio_mq_setattr.c: New file. ++ * kaio_mq_timedreceive.c: New file. ++ * kaio_mq_timedsend.c: New file. ++ * kaio_mq_unlink.c: New file. ++ * sysdeps/pthread/tst-mqueue8x.c: New file. ++ * sysdeps/unix/sysv/linux/syscalls.list: New file. ++ * tst-mqueue8.c: New file. ++ * tst-mqueue9.c: New file. ++ * tst-timer5.c: New file. ++ * tst-aiod.h: New file. ++ * tst-aiod.c: New test. ++ * tst-aiod64.c: New test. ++ * tst-aiod2.c: New test. ++ * tst-aiod3.c: New test. ++ * tst-aiod4.c: New test. ++ * tst-aiod5.c: New test. ++ * sysdeps/mips/Makefile: New file. ++ * sysdeps/unix/alpha/Makefile: New file. ++ * sysdeps/unix/alpha/rtkaio-sysdep.S: New file. ++ * sysdeps/unix/mips/rtkaio-sysdep.S: New file. ++ * sysdeps/unix/sysv/linux/Makefile: New file. ++ * sysdeps/unix/sysv/linux/s390/Makefile: New file. ++ * sysdeps/unix/sysv/linux/s390/rtkaio-sysdep.S: New file. ++ * sysdeps/unix/sysv/linux/powerpc/Makefile: New file. ++ * sysdeps/unix/sysv/linux/powerpc/rtkaio-sysdep.c: New file. ++ * sysdeps/unix/sysv/linux/ia64/Makefile: New file. ++ * sysdeps/unix/sysv/linux/ia64/rtkaio-sysdep.S: New file. ++ ++2004-04-17 Jakub Jelinek ++ ++ * rt/Makefile (mq-routines): Set. ++ (librt-routines): Use it. ++ (tests): Add tst-mqueue{1,2,3,4,5,6,7} and tst-timer{3,4}. ++ (tst-mqueue7-ARGS): Set. ++ * rt/Versions (librt): Add mq_*@@GLIBC_2.3.4. ++ * rt/tst-mqueue1.c: New file. ++ * rt/tst-mqueue2.c: New file. ++ * rt/tst-mqueue3.c: New file. ++ * rt/tst-mqueue4.c: New file. ++ * rt/tst-mqueue5.c: New file. ++ * rt/tst-mqueue6.c: New file. ++ * rt/tst-mqueue7.c: New file. ++ * rt/tst-timer3.c: New file. ++ * rt/tst-timer4.c: New file. ++ ++2003-08-14 Jakub Jelinek ++ ++ * sysdeps/unix/sysv/linux/kaio_misc.c (wait_for_kernel_requests): ++ New function. ++ (handle_fildes_io): Use it for LIO_SYNC and LIO_DSYNC. ++ ++ * sysdeps/pthread/Makefile (CPPFLAGS): Add -DBROKEN_THREAD_SIGNALS ++ for rtkaio/linuxthreads combo. ++ * sysdeps/unix/sysv/linux/kaio_misc.c (__aio_enqueue_request_ctx): ++ Only set caller_pid if BROKEN_THREAD_SIGNALS. ++ * sysdeps/unix/sysv/linux/kaio_misc.h (struct waitlist, ++ struct requestlist): Remove caller_pid unless BROKEN_THREAD_SIGNALS. ++ (__aio_notify_only): Remove last argument if not ++ BROKEN_THREAD_SIGNALS. ++ * sysdeps/unix/sysv/linux/kaio_suspend.c (aio_suspend): Only set ++ caller_pid if not BROKEN_THREAD_SIGNALS. ++ * sysdeps/unix/sysv/linux/klio_listio.c (lio_listio): Likewise. ++ Remove last argument in call to __aio_notify_only unless ++ BROKEN_THREAD_SIGNALS. ++ ++ * tst-aio.c: Avoid test duplication. Include rt/aio.c instead. ++ * tst-aio2.c: Similarly. ++ * tst-aio3.c: Similarly. ++ * tst-aio4.c: Similarly. ++ * tst-aio5.c: Similarly. ++ * tst-aio6.c: Similarly. ++ * tst-aio64.c: Similarly. ++ * tst-aio7.c: Similarly. ++ * tst-clock.c: Similarly. ++ * tst-clock_nanosleep.c: Similarly. ++ * tst-shm.c: Similarly. ++ * tst-timer2.c: Similarly. ++ ++2003-07-29 Roland McGrath ++ ++ * rt/tst-timer2.c: New file. ++ * rt/Makefile (tests): Add it. ++ ++2003-07-25 Jakub Jelinek ++ ++ * sysdeps/unix/sysv/linux/kaio_cancel.c (aio_cancel): Attempt ++ to cancel kioctx != KCTX_NONE requests even if second argument ++ to aio_cancel is NULL. ++ ++2003-07-24 Jakub Jelinek ++ ++ * sysdeps/unix/sysv/linux/kaio_cancel.c (aio_cancel): Return ++ AIO_ALLDONE if aiocbp != NULL and has already completed. Return ++ -1/EINVAL if aiocbp->aio_fildes does not match fildes. ++ ++ * sysdeps/unix/sysv/linux/alpha/kaio_cancel.c: New file. ++ * sysdeps/unix/sysv/linux/hppa/kaio_cancel.c: New file. ++ * sysdeps/unix/sysv/linux/sparc/kaio_cancel.c: New file. ++ * sysdeps/unix/sysv/linux/kaio_cancel.c (aio_cancel): Attempt ++ to cancel request handled by kernel (so far just if aiocbp != NULL). ++ * sysdeps/unix/sysv/linux/kaio_misc.c (__aio_remove_krequest): Fix ++ assertion, req->kioctx must NOT be KCTX_NONE. ++ * sysdeps/unix/sysv/linux/kaio_misc.h (__aio_remove_krequest): New ++ prototype. ++ ++2003-07-23 Jakub Jelinek ++ ++ * New add-on. +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/configure glibc-2.17-931-g30bbc0c.new/rtkaio/configure +--- glibc-2.17-931-g30bbc0c/rtkaio/configure 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/configure 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1,4 @@ ++# This file is generated from configure.in by Autoconf. DO NOT EDIT! ++ ++libc_add_on_canonical= ++libc_add_on_subdirs=. +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/configure.in glibc-2.17-931-g30bbc0c.new/rtkaio/configure.in +--- glibc-2.17-931-g30bbc0c/rtkaio/configure.in 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/configure.in 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1,5 @@ ++dnl glibc configure fragment for rtkaio add-on ++GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory. ++ ++libc_add_on_canonical= ++libc_add_on_subdirs=. +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/Depend glibc-2.17-931-g30bbc0c.new/rtkaio/Depend +--- glibc-2.17-931-g30bbc0c/rtkaio/Depend 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/Depend 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++rt +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_cancel.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_cancel.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_cancel.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_cancel.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_clock_getcpuclockid.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_clock_getcpuclockid.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_clock_getcpuclockid.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_clock_getcpuclockid.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_clock_getres.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_clock_getres.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_clock_getres.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_clock_getres.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_clock_gettime.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_clock_gettime.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_clock_gettime.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_clock_gettime.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_clock_nanosleep.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_clock_nanosleep.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_clock_nanosleep.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_clock_nanosleep.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_clock_settime.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_clock_settime.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_clock_settime.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_clock_settime.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_error.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_error.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_error.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_error.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_fsync.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_fsync.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_fsync.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_fsync.c 2013-08-16 16:23:23.241028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_get_clockfreq.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_get_clockfreq.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_get_clockfreq.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_get_clockfreq.c 2013-08-16 16:23:23.241028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_misc.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_misc.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_misc.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_misc.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_close.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_close.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_close.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_close.c 2013-08-16 16:23:23.241028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_getattr.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_getattr.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_getattr.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_getattr.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_notify.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_notify.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_notify.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_notify.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_open.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_open.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_open.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_open.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_receive.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_receive.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_receive.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_receive.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_send.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_send.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_send.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_send.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_setattr.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_setattr.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_setattr.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_setattr.c 2013-08-16 16:23:23.247028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_timedreceive.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_timedreceive.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_timedreceive.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_timedreceive.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_timedsend.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_timedsend.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_timedsend.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_timedsend.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_unlink.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_unlink.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_mq_unlink.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_mq_unlink.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_notify.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_notify.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_notify.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_notify.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_read64.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_read64.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_read64.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_read64.c 2013-08-16 16:23:23.247028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_read.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_read.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_read.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_read.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_return.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_return.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_return.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_return.c 2013-08-16 16:23:23.247028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_shm_open.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_shm_open.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_shm_open.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_shm_open.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_shm_unlink.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_shm_unlink.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_shm_unlink.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_shm_unlink.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_sigqueue.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_sigqueue.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_sigqueue.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_sigqueue.c 2013-08-16 16:23:23.247028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_suspend.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_suspend.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_suspend.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_suspend.c 2013-08-16 16:23:23.247028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_timer_create.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_timer_create.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_timer_create.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_timer_create.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_timer_delete.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_timer_delete.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_timer_delete.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_timer_delete.c 2013-08-16 16:23:23.247028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_timer_getoverr.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_timer_getoverr.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_timer_getoverr.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_timer_getoverr.c 2013-08-16 16:23:23.241028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_timer_gettime.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_timer_gettime.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_timer_gettime.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_timer_gettime.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_timer_settime.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_timer_settime.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_timer_settime.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_timer_settime.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_write64.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_write64.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_write64.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_write64.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/kaio_write.c glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_write.c +--- glibc-2.17-931-g30bbc0c/rtkaio/kaio_write.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/kaio_write.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/klio_listio64.c glibc-2.17-931-g30bbc0c.new/rtkaio/klio_listio64.c +--- glibc-2.17-931-g30bbc0c/rtkaio/klio_listio64.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/klio_listio64.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/klio_listio.c glibc-2.17-931-g30bbc0c.new/rtkaio/klio_listio.c +--- glibc-2.17-931-g30bbc0c/rtkaio/klio_listio.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/klio_listio.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/Makefile glibc-2.17-931-g30bbc0c.new/rtkaio/Makefile +--- glibc-2.17-931-g30bbc0c/rtkaio/Makefile 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/Makefile 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1,101 @@ ++# Copyright (C) 2003, 2004, 2006 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, write to the Free ++# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++# 02111-1307 USA. ++ ++# ++# Sub-makefile for real-time kaio portion of the library. ++# ++subdir := rtkaio ++ ++aio-routines := aio_cancel aio_error aio_fsync aio_misc aio_read \ ++ aio_read64 aio_return aio_suspend aio_write \ ++ aio_write64 lio_listio lio_listio64 aio_sigqueue \ ++ aio_notify ++clock-routines := get_clockfreq clock_getcpuclockid \ ++ clock_getres clock_gettime clock_settime \ ++ clock_nanosleep ++timer-routines := timer_create timer_delete timer_getoverr \ ++ timer_gettime timer_settime ++shm-routines := shm_open shm_unlink ++mq-routines := mq_open mq_close mq_unlink mq_getattr mq_setattr \ ++ mq_notify mq_send mq_receive mq_timedsend \ ++ mq_timedreceive ++ ++librtkaio-routines = $(patsubst %,k%,$(aio-routines)) \ ++ $(patsubst %,kaio_%,$(clock-routines) $(timer-routines) \ ++ $(shm-routines) $(mq-routines)) ++ ++tests := tst-shm tst-clock tst-clock_nanosleep tst-timer tst-timer2 \ ++ tst-aio tst-aio64 tst-aio2 tst-aio3 tst-aio4 tst-aio5 tst-aio6 \ ++ tst-aio7 tst-aio8 tst-aio9 tst-aio10 \ ++ tst-mqueue1 tst-mqueue2 tst-mqueue3 tst-mqueue4 \ ++ tst-mqueue5 tst-mqueue6 tst-mqueue7 tst-mqueue8 tst-mqueue9 \ ++ tst-timer3 tst-timer4 tst-timer5 \ ++ tst-cpuclock1 tst-cpuclock2 \ ++ tst-cputimer1 tst-cputimer2 tst-cputimer3 \ ++ tst-clock2 \ ++ tst-aiod tst-aiod64 tst-aiod2 tst-aiod3 tst-aiod4 tst-aiod5 ++ ++extra-libs := librtkaio ++extra-libs-others := $(extra-libs) ++ ++include $(..)Makeconfig ++ ++ifeq (yesyes,$(build-shared)$(elf)) ++generated += librt.so$(librt.so-version) ++ ++$(objpfx)librt.so$(librt.so-version): $(objpfx)librtkaio.so; $(make-link) ++endif ++ ++include $(..)Rules ++ ++CFLAGS-kaio_suspend.c = -fexceptions ++CFLAGS-kaio_clock_nanosleep.c = -fexceptions -fasynchronous-unwind-tables ++CFLAGS-kaio_librt-cancellation.c = -fasynchronous-unwind-tables ++ ++LDFLAGS-rtkaio.so = -Wl,-soname=lib$(libprefix)rt.so$(librt.so-version) \ ++ -Wl,--enable-new-dtags,-z,nodelete ++CPPFLAGS-librtkaio += -DIS_IN_librt=1 -I$(..)rt ++ ++rpath-dirs := $(patsubst rt,rtkaio,$(rpath-dirs)) ++ ++ifeq (yesyes,$(build-shared)$(elf)) ++others: $(objpfx)librt.so$(librt.so-version) ++endif ++ ++# Depend on libc.so so a DT_NEEDED is generated in the shared objects. ++# This ensures they will load libc.so for needed symbols if loaded by ++# a statically-linked program that hasn't already loaded it. ++$(objpfx)librtkaio.so: $(common-objpfx)libc.so $(common-objpfx)libc_nonshared.a \ ++ $(shared-thread-library) \ ++ $(if $(filter yes,$(elf)), $(elfobjdir)/ld.so) ++ ++ifeq (yes,$(build-shared)) ++$(addprefix $(objpfx),$(tests)): $(objpfx)librtkaio.so $(shared-thread-library) ++else ++$(addprefix $(objpfx),$(tests)): $(objpfx)librtkaio.a $(static-thread-library) ++endif ++ifeq (yes,$(build-bounded)) ++$(tests:%=$(objpfx)%-bp): $(objpfx)librtkaio_b.a $(bounded-thread-library) ++endif ++ ++tst-mqueue7-ARGS = -- $(built-program-cmd) ++ ++ifeq (yes,$(build-static-nss)) ++otherlibs += $(nssobjdir)/libnss_files.a $(resolvobjdir)/libnss_dns.a \ ++ $(resolvobjdir)/libresolv.a ++endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/shlib-versions glibc-2.17-931-g30bbc0c.new/rtkaio/shlib-versions +--- glibc-2.17-931-g30bbc0c/rtkaio/shlib-versions 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/shlib-versions 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1,2 @@ ++mips.*-.*-linux.* librtkaio=1 GLIBC_2.0 GLIBC_2.2 ++.*-.*-.* librtkaio=1 +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/kaio_timer_routines.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/kaio_timer_routines.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/kaio_timer_routines.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/kaio_timer_routines.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/librtkaio-cancellation.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/librtkaio-cancellation.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/librtkaio-cancellation.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/librtkaio-cancellation.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/Makefile glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/Makefile +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/Makefile 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/Makefile 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1,39 @@ ++ifeq ($(filter nptl,$(sorted-subdirs)),nptl) ++ ++ifeq ($(subdir),rtkaio) ++librtkaio-sysdep_routines += kaio_timer_routines librtkaio-cancellation rtkaio-unwind-resume ++librtkaio-shared-only-routines += rtkaio-unwind-resume ++tests += tst-cancel17 tst-cancelx17 ++CPPFLAGS-kaio_timer_routines.c = -I../nptl ++CFLAGS-librtkaio-cancellation.c += -fexceptions -fasynchronous-unwind-tables ++CFLAGS-rtkaio-unwind-resume.c += -fexceptions -fasynchronous-unwind-tables ++CFLAGS-tst-cancelx17.c += -fexceptions ++ ++ifeq (yes,$(build-shared)) ++$(objpfx)tst-timer: $(objpfx)librtkaio.so $(shared-thread-library) ++else ++$(objpfx)tst-timer: $(objpfx)librtkaio.a $(static-thread-library) ++endif ++ ++ifeq ($(have-forced-unwind),yes) ++tests += tst-mqueue8x ++CFLAGS-tst-mqueue8x.c += -fexceptions ++endif ++endif ++ ++endif ++ ++ifeq ($(filter linuxthreads,$(sorted-subdirs)),linuxthreads) ++ ++ifeq ($(subdir),rtkaio) ++librtkaio-sysdep_routines += kaio_timer_routines ++CPPFLAGS += -DBROKEN_THREAD_SIGNALS ++ ++ifeq (yes,$(build-shared)) ++$(objpfx)tst-timer: $(objpfx)librtkaio.so $(shared-thread-library) ++else ++$(objpfx)tst-timer: $(objpfx)librtkaio.a $(static-thread-library) ++endif ++endif ++ ++endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/rtkaio-unwind-resume.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/rtkaio-unwind-resume.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/rtkaio-unwind-resume.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/rtkaio-unwind-resume.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/tst-cancel17.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/tst-cancel17.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/tst-cancel17.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/tst-cancel17.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/tst-cancelx17.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/tst-cancelx17.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/tst-cancelx17.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/tst-cancelx17.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include "tst-cancel17.c" +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/tst-mqueue8x.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/tst-mqueue8x.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/tst-mqueue8x.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/tst-mqueue8x.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include_next +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/tst-timer.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/tst-timer.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/tst-timer.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/tst-timer.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include_next +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/Versions glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/Versions +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/pthread/Versions 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/pthread/Versions 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1,7 @@ ++%ifdef HAVE_FORCED_UNWIND ++librtkaio { ++ GLIBC_2.4 { ++ lio_listio; lio_listio64; ++ } ++} ++%endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/alpha/Makefile glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/alpha/Makefile +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/alpha/Makefile 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/alpha/Makefile 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,3 @@ ++ifeq ($(subdir),rtkaio) ++librtkaio-sysdep_routines += rtkaio-sysdep ++endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/alpha/rtkaio-sysdep.S glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/alpha/rtkaio-sysdep.S +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/alpha/rtkaio-sysdep.S 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/alpha/rtkaio-sysdep.S 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/alpha/kaio_cancel.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/alpha/kaio_cancel.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/alpha/kaio_cancel.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/alpha/kaio_cancel.c 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,33 @@ ++#include ++ ++#define aio_cancel64 XXX ++#include ++#undef aio_cancel64 ++#include ++ ++extern __typeof (aio_cancel) __new_aio_cancel; ++extern __typeof (aio_cancel) __old_aio_cancel; ++ ++#define aio_cancel __new_aio_cancel ++ ++#include ++ ++#undef aio_cancel ++strong_alias (__new_aio_cancel, __new_aio_cancel64); ++versioned_symbol (librt, __new_aio_cancel, aio_cancel, GLIBC_2_3); ++versioned_symbol (librt, __new_aio_cancel64, aio_cancel64, GLIBC_2_3); ++ ++#if SHLIB_COMPAT (librt, GLIBC_2_1, GLIBC_2_3) ++ ++#undef ECANCELED ++#define aio_cancel __old_aio_cancel ++#define ECANCELED 125 ++ ++#include ++ ++#undef aio_cancel ++strong_alias (__old_aio_cancel, __old_aio_cancel64); ++compat_symbol (librt, __old_aio_cancel, aio_cancel, GLIBC_2_1); ++compat_symbol (librt, __old_aio_cancel64, aio_cancel64, GLIBC_2_1); ++ ++#endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/alpha/Versions glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/alpha/Versions +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/alpha/Versions 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/alpha/Versions 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,6 @@ ++librtkaio { ++ GLIBC_2.3 { ++ # AIO functions. ++ aio_cancel; aio_cancel64; ++ } ++} +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/ia64/Makefile glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/ia64/Makefile +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/ia64/Makefile 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/ia64/Makefile 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,3 @@ ++ifeq ($(subdir),rtkaio) ++librtkaio-routines += rtkaio-sysdep ++endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/ia64/rtkaio-sysdep.S glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/ia64/rtkaio-sysdep.S +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/ia64/rtkaio-sysdep.S 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/ia64/rtkaio-sysdep.S 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/ia64/Versions glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/ia64/Versions +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/ia64/Versions 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/ia64/Versions 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,9 @@ ++%ifdef HAVE_FORCED_UNWIND ++librtkaio { ++ GLIBC_2.3.3 { ++ # Changed timer_t. ++ timer_create; timer_delete; timer_getoverrun; timer_gettime; ++ timer_settime; ++ } ++} ++%endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_cancel.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_cancel.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_cancel.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_cancel.c 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,240 @@ ++/* Cancel requests associated with given file descriptor. ++ Copyright (C) 1997, 1998, 2000, 2002, 2003, 2005 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 1997. ++ ++ 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. */ ++ ++/* We use an UGLY hack to prevent gcc from finding us cheating. The ++ implementation of aio_cancel and aio_cancel64 are identical and so ++ we want to avoid code duplication by using aliases. But gcc sees ++ the different parameter lists and prints a warning. We define here ++ a function so that aio_cancel64 has no prototype. */ ++#ifndef aio_cancel ++#define aio_cancel64 XXX ++#include ++/* And undo the hack. */ ++#undef aio_cancel64 ++#endif ++ ++#include ++ ++#ifndef USE_KAIO ++#include ++#else ++ ++#include ++#include ++#include ++#include ++ ++int ++aio_cancel (fildes, aiocbp) ++ int fildes; ++ struct aiocb *aiocbp; ++{ ++ struct requestlist *req = NULL; ++ int result = AIO_ALLDONE; ++ ++ /* If fildes is invalid, error. */ ++ if (fcntl (fildes, F_GETFL) < 0) ++ { ++ __set_errno (EBADF); ++ return -1; ++ } ++ ++ /* Request the mutex. */ ++ pthread_mutex_lock (&__aio_requests_mutex); ++ ++ /* We are asked to cancel a specific AIO request. */ ++ if (aiocbp != NULL) ++ { ++ /* If the AIO request is not for this descriptor it has no value ++ to look for the request block. */ ++ if (aiocbp->aio_fildes != fildes) ++ { ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ __set_errno (EINVAL); ++ return -1; ++ } ++ else if (aiocbp->__error_code == EINPROGRESS) ++ { ++ struct requestlist *last = NULL; ++ ++ req = __aio_find_req_fd (fildes); ++ ++ if (req != NULL) ++ while (req->aiocbp != (aiocb_union *) aiocbp) ++ { ++ last = req; ++ req = req->next_prio; ++ if (req == NULL) ++ break; ++ } ++ ++ if (req != NULL) ++ { ++ /* Don't remove the entry if a thread is already working on ++ it. */ ++ if (req->running == allocated) ++ { ++ result = AIO_NOTCANCELED; ++ req = NULL; ++ } ++ else ++ { ++ /* We can remove the entry. */ ++ __aio_remove_request (last, req, 0); ++ ++ result = AIO_CANCELED; ++ ++ req->next_prio = NULL; ++ } ++ } ++ else ++ { ++ /* Try kernel requests. */ ++ req = __aio_find_req ((aiocb_union *) aiocbp); ++ ++ if (req == NULL) ++ { ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ __set_errno (EINVAL); ++ return -1; ++ } ++ ++ assert (req->kioctx != KCTX_NONE); ++ ++ /* If kernel is working on it, try cancelling it. */ ++ if (req->running == allocated) ++ { ++ struct kio_event ev; ++ INTERNAL_SYSCALL_DECL (err); ++ int res; ++ ++ res = INTERNAL_SYSCALL (io_cancel, err, 3, __aio_kioctx, ++ &req->kiocb, &ev); ++ if (INTERNAL_SYSCALL_ERROR_P (res, err)) ++ { ++ result = AIO_NOTCANCELED; ++ req = NULL; ++ } ++ else ++ req->running = queued; ++ } ++ if (req != NULL) ++ { ++ /* We can remove the entry. */ ++ __aio_remove_krequest (req); ++ result = AIO_CANCELED; ++ req->next_prio = NULL; ++ } ++ } ++ } ++ } ++ else ++ { ++ /* Find the beginning of the list of all requests for this ++ desriptor. */ ++ req = __aio_find_req_fd (fildes); ++ ++ /* If any request is worked on by a thread it must be the first. ++ So either we can delete all requests or all but the first. */ ++ if (req != NULL) ++ { ++ if (req->running == allocated) ++ { ++ struct requestlist *old = req; ++ req = req->next_prio; ++ old->next_prio = NULL; ++ ++ result = AIO_NOTCANCELED; ++ ++ if (req != NULL) ++ __aio_remove_request (old, req, 1); ++ } ++ else ++ { ++ result = AIO_CANCELED; ++ ++ /* We can remove the entry. */ ++ __aio_remove_request (NULL, req, 1); ++ } ++ } ++ ++ if (result != AIO_NOTCANCELED) ++ { ++ /* Try to cancel kernel requests. */ ++ struct requestlist *kreq = __aio_find_kreq_fd (fildes); ++ ++ while (kreq) ++ { ++ struct requestlist *next; ++ ++ /* If kernel is working on it, try cancelling it. */ ++ if (kreq->running == allocated) ++ { ++ struct kio_event ev; ++ INTERNAL_SYSCALL_DECL (err); ++ int res; ++ ++ res = INTERNAL_SYSCALL (io_cancel, err, 3, __aio_kioctx, ++ &kreq->kiocb, &ev); ++ if (INTERNAL_SYSCALL_ERROR_P (res, err)) ++ { ++ result = AIO_NOTCANCELED; ++ break; ++ } ++ else ++ kreq->running = queued; ++ } ++ next = kreq->next_prio; ++ __aio_remove_krequest (kreq); ++ result = AIO_CANCELED; ++ kreq->next_prio = NULL; ++ assert (kreq->running == yes || kreq->running == queued); ++ kreq->aiocbp->aiocb.__error_code = ECANCELED; ++ kreq->aiocbp->aiocb.__return_value = -1; ++ __aio_notify (kreq); ++ __aio_free_request (kreq); ++ kreq = next; ++ } ++ } ++ } ++ ++ /* Mark requests as canceled and send signal. */ ++ while (req != NULL) ++ { ++ struct requestlist *old = req; ++ assert (req->running == yes || req->running == queued); ++ req->aiocbp->aiocb.__error_code = ECANCELED; ++ req->aiocbp->aiocb.__return_value = -1; ++ __aio_notify (req); ++ req = req->next_prio; ++ __aio_free_request (old); ++ } ++ ++ /* Release the mutex. */ ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ ++ return result; ++} ++ ++#ifndef aio_cancel ++weak_alias (aio_cancel, aio_cancel64) ++#endif ++ ++#endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_error.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_error.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_error.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_error.c 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,54 @@ ++/* Return error status of asynchronous I/O request. ++ Copyright (C) 1997, 2002, 2003 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 1997. ++ ++ 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. */ ++ ++/* We use an UGLY hack to prevent gcc from finding us cheating. The ++ implementation of aio_error and aio_error64 are identical and so ++ we want to avoid code duplication by using aliases. But gcc sees ++ the different parameter lists and prints a warning. We define here ++ a function so that aio_error64 has no prototype. */ ++#define aio_error64 XXX ++#include ++/* And undo the hack. */ ++#undef aio_error64 ++ ++#include ++ ++#ifndef USE_KAIO ++#include ++#else ++ ++#include ++ ++int ++aio_error (aiocbp) ++ const struct aiocb *aiocbp; ++{ ++ int ret = aiocbp->__error_code; ++ ++ if (ret == EINPROGRESS) ++ { ++ __aio_read_one_event (); ++ ret = aiocbp->__error_code; ++ } ++ return ret; ++} ++ ++weak_alias (aio_error, aio_error64) ++#endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_fsync.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_fsync.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_fsync.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_fsync.c 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,6 @@ ++#define aio_fsync64 XXX ++#include ++/* And undo the hack. */ ++#undef aio_fsync64 ++#include ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.c 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,1139 @@ ++/* Handle general operations. ++ Copyright (C) 1997,1998,1999,2000,2001,2002,2003,2006,2010 ++ Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 1997. ++ ++ 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 ++ ++#ifndef USE_KAIO ++#include ++#else ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifndef aio_create_helper_thread ++# define aio_create_helper_thread __aio_create_helper_thread ++ ++extern inline int ++__aio_create_helper_thread (pthread_t *threadp, void *(*tf) (void *), void *arg) ++{ ++ pthread_attr_t attr; ++ ++ /* Make sure the thread is created detached. */ ++ pthread_attr_init (&attr); ++ pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); ++ ++ int ret = pthread_create (threadp, &attr, tf, arg); ++ ++ (void) pthread_attr_destroy (&attr); ++ return ret; ++} ++ ++#endif ++ ++ ++static void add_request_to_runlist (struct requestlist *newrequest) ++ internal_function; ++static int add_request_to_list (struct requestlist *newrequest, int fildes, ++ int prio) ++ internal_function; ++static void * handle_kernel_aio (void *arg); ++static void kernel_callback (kctx_t ctx, struct kiocb *kiocb, long res, ++ long res2); ++ ++/* Pool of request list entries. */ ++static struct requestlist **pool; ++ ++/* Number of total and allocated pool entries. */ ++static size_t pool_max_size; ++static size_t pool_size; ++ ++/* Kernel AIO context. */ ++kctx_t __aio_kioctx = KCTX_NONE; ++int __have_no_kernel_aio; ++int __kernel_thread_started; ++ ++/* We implement a two dimensional array but allocate each row separately. ++ The macro below determines how many entries should be used per row. ++ It should better be a power of two. */ ++#define ENTRIES_PER_ROW 32 ++ ++/* How many rows we allocate at once. */ ++#define ROWS_STEP 8 ++ ++/* List of available entries. */ ++static struct requestlist *freelist; ++ ++/* List of request waiting to be processed. */ ++static struct requestlist *runlist; ++ ++/* Structure list of all currently processed requests. */ ++static struct requestlist *requests, *krequests; ++ ++/* Number of threads currently running. */ ++static int nthreads; ++ ++/* Number of threads waiting for work to arrive. */ ++static int idle_thread_count; ++ ++ ++/* These are the values used to optimize the use of AIO. The user can ++ overwrite them by using the `aio_init' function. */ ++static struct aioinit optim = ++{ ++ 20, /* int aio_threads; Maximal number of threads. */ ++ 64, /* int aio_num; Number of expected simultanious requests. */ ++ 0, ++ 0, ++ 0, ++ 0, ++ 1, ++ 0 ++}; ++ ++ ++/* Since the list is global we need a mutex protecting it. */ ++pthread_mutex_t __aio_requests_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; ++ ++/* When you add a request to the list and there are idle threads present, ++ you signal this condition variable. When a thread finishes work, it waits ++ on this condition variable for a time before it actually exits. */ ++pthread_cond_t __aio_new_request_notification = PTHREAD_COND_INITIALIZER; ++ ++ ++/* Functions to handle request list pool. */ ++static struct requestlist * ++get_elem (void) ++{ ++ struct requestlist *result; ++ ++ if (freelist == NULL) ++ { ++ struct requestlist *new_row; ++ int cnt; ++ ++ assert (sizeof (struct aiocb) == sizeof (struct aiocb64)); ++ ++ if (pool_size + 1 >= pool_max_size) ++ { ++ size_t new_max_size = pool_max_size + ROWS_STEP; ++ struct requestlist **new_tab; ++ ++ new_tab = (struct requestlist **) ++ realloc (pool, new_max_size * sizeof (struct requestlist *)); ++ ++ if (new_tab == NULL) ++ return NULL; ++ ++ pool_max_size = new_max_size; ++ pool = new_tab; ++ } ++ ++ /* Allocate the new row. */ ++ cnt = pool_size == 0 ? optim.aio_num : ENTRIES_PER_ROW; ++ new_row = (struct requestlist *) calloc (cnt, ++ sizeof (struct requestlist)); ++ if (new_row == NULL) ++ return NULL; ++ ++ pool[pool_size++] = new_row; ++ ++ /* Put all the new entries in the freelist. */ ++ do ++ { ++ new_row->next_prio = freelist; ++ freelist = new_row++; ++ } ++ while (--cnt > 0); ++ } ++ ++ result = freelist; ++ freelist = freelist->next_prio; ++ ++ return result; ++} ++ ++ ++void ++internal_function ++__aio_free_request (struct requestlist *elem) ++{ ++ elem->running = no; ++ elem->next_prio = freelist; ++ freelist = elem; ++} ++ ++ ++struct requestlist * ++internal_function ++__aio_find_req (aiocb_union *elem) ++{ ++ struct requestlist *runp; ++ int fildes = elem->aiocb.aio_fildes; ++ int i; ++ ++ for (i = 0; i < 2; i++) ++ { ++ runp = i ? requests : krequests; ++ ++ while (runp != NULL && runp->aiocbp->aiocb.aio_fildes < fildes) ++ runp = runp->next_fd; ++ ++ if (runp != NULL) ++ { ++ if (runp->aiocbp->aiocb.aio_fildes != fildes) ++ runp = NULL; ++ else ++ while (runp != NULL && runp->aiocbp != elem) ++ runp = runp->next_prio; ++ if (runp != NULL) ++ return runp; ++ } ++ } ++ ++ return NULL; ++} ++ ++ ++struct requestlist * ++internal_function ++__aio_find_req_fd (int fildes) ++{ ++ struct requestlist *runp = requests; ++ ++ while (runp != NULL && runp->aiocbp->aiocb.aio_fildes < fildes) ++ runp = runp->next_fd; ++ ++ return (runp != NULL && runp->aiocbp->aiocb.aio_fildes == fildes ++ ? runp : NULL); ++} ++ ++ ++struct requestlist * ++internal_function ++__aio_find_kreq_fd (int fildes) ++{ ++ struct requestlist *runp = krequests; ++ ++ while (runp != NULL && runp->aiocbp->aiocb.aio_fildes < fildes) ++ runp = runp->next_fd; ++ ++ return (runp != NULL && runp->aiocbp->aiocb.aio_fildes == fildes ++ ? runp : NULL); ++} ++ ++ ++void ++internal_function ++__aio_remove_request (struct requestlist *last, struct requestlist *req, ++ int all) ++{ ++ assert (req->running == yes || req->running == queued ++ || req->running == done); ++ assert (req->kioctx == KCTX_NONE); ++ ++ if (last != NULL) ++ last->next_prio = all ? NULL : req->next_prio; ++ else ++ { ++ if (all || req->next_prio == NULL) ++ { ++ if (req->last_fd != NULL) ++ req->last_fd->next_fd = req->next_fd; ++ else ++ requests = req->next_fd; ++ if (req->next_fd != NULL) ++ req->next_fd->last_fd = req->last_fd; ++ } ++ else ++ { ++ if (req->last_fd != NULL) ++ req->last_fd->next_fd = req->next_prio; ++ else ++ requests = req->next_prio; ++ ++ if (req->next_fd != NULL) ++ req->next_fd->last_fd = req->next_prio; ++ ++ req->next_prio->last_fd = req->last_fd; ++ req->next_prio->next_fd = req->next_fd; ++ ++ /* Mark this entry as runnable. */ ++ req->next_prio->running = yes; ++ } ++ ++ if (req->running == yes) ++ { ++ struct requestlist *runp = runlist; ++ ++ last = NULL; ++ while (runp != NULL) ++ { ++ if (runp == req) ++ { ++ if (last == NULL) ++ runlist = runp->next_run; ++ else ++ last->next_run = runp->next_run; ++ break; ++ } ++ last = runp; ++ runp = runp->next_run; ++ } ++ } ++ } ++} ++ ++void ++internal_function ++__aio_remove_krequest (struct requestlist *req) ++{ ++ assert (req->running == yes || req->running == queued ++ || req->running == done); ++ assert (req->kioctx != KCTX_NONE); ++ ++ if (req->prev_prio != NULL) ++ { ++ req->prev_prio->next_prio = req->next_prio; ++ if (req->next_prio != NULL) ++ req->next_prio->prev_prio = req->prev_prio; ++ } ++ else if (req->next_prio == NULL) ++ { ++ if (req->last_fd != NULL) ++ req->last_fd->next_fd = req->next_fd; ++ else ++ krequests = req->next_fd; ++ if (req->next_fd != NULL) ++ req->next_fd->last_fd = req->last_fd; ++ } ++ else ++ { ++ if (req->last_fd != NULL) ++ req->last_fd->next_fd = req->next_prio; ++ else ++ krequests = req->next_prio; ++ if (req->next_fd != NULL) ++ req->next_fd->last_fd = req->next_prio; ++ ++ req->next_prio->prev_prio = NULL; ++ req->next_prio->last_fd = req->last_fd; ++ req->next_prio->next_fd = req->next_fd; ++ } ++} ++ ++ ++/* The thread handler. */ ++static void *handle_fildes_io (void *arg); ++static int wait_for_kernel_requests (int fildes); ++ ++ ++/* User optimization. */ ++void ++__aio_init (const struct aioinit *init) ++{ ++ /* Get the mutex. */ ++ pthread_mutex_lock (&__aio_requests_mutex); ++ ++ /* Only allow writing new values if the table is not yet allocated. */ ++ if (pool == NULL) ++ { ++ optim.aio_threads = init->aio_threads < 1 ? 1 : init->aio_threads; ++ optim.aio_num = (init->aio_num < ENTRIES_PER_ROW ++ ? ENTRIES_PER_ROW ++ : init->aio_num & ~ENTRIES_PER_ROW); ++ } ++ ++ if (init->aio_idle_time != 0) ++ optim.aio_idle_time = init->aio_idle_time; ++ ++ /* Release the mutex. */ ++ pthread_mutex_unlock (&__aio_requests_mutex); ++} ++weak_alias (__aio_init, aio_init) ++ ++static void ++kernel_callback (kctx_t ctx, struct kiocb *kiocb, long res, long res2) ++{ ++ struct requestlist *req = (struct requestlist *)kiocb; ++ long errcode = 0; ++ ++ if (res < 0 && res > -1000) ++ { ++ errcode = -res; ++ res = -1; ++ } ++ req->aiocbp->aiocb.__return_value = res; ++ atomic_write_barrier (); ++ req->aiocbp->aiocb.__error_code = errcode; ++ __aio_notify (req); ++ assert (req->running == allocated); ++ req->running = done; ++ __aio_remove_krequest (req); ++ __aio_free_request (req); ++} ++ ++void ++internal_function ++__aio_read_one_event (void) ++{ ++ struct kio_event ev[10]; ++ struct timespec ts; ++ int count, i; ++ ++ if (__aio_kioctx == KCTX_NONE) ++ return; ++ ts.tv_sec = 0; ++ ts.tv_nsec = 0; ++ do ++ { ++ INTERNAL_SYSCALL_DECL (err); ++ count = INTERNAL_SYSCALL (io_getevents, err, 5, __aio_kioctx, 0, 10, ++ ev, &ts); ++ if (INTERNAL_SYSCALL_ERROR_P (count, err) || count == 0) ++ break; ++ pthread_mutex_lock (&__aio_requests_mutex); ++ for (i = 0; i < count; i++) ++ { ++ void (*cb)(kctx_t, struct kiocb *, long, long); ++ ++ cb = (void *) (uintptr_t) ev[i].kioe_data; ++ cb (__aio_kioctx, (struct kiocb *) (uintptr_t) ev[i].kioe_obj, ++ ev[i].kioe_res, ev[i].kioe_res2); ++ } ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ } ++ while (count == 10); ++} ++ ++int ++internal_function ++__aio_wait_for_events (kctx_t kctx, const struct timespec *timespec) ++{ ++ int ret, i; ++ struct kio_event ev[10]; ++ struct timespec ts; ++ INTERNAL_SYSCALL_DECL (err); ++ ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ ts.tv_sec = 0; ++ ts.tv_nsec = 0; ++ do ++ { ++ ret = INTERNAL_SYSCALL (io_getevents, err, 5, kctx, 1, 10, ev, ++ timespec); ++ if (INTERNAL_SYSCALL_ERROR_P (ret, err) || ret == 0) ++ break; ++ ++ pthread_mutex_lock (&__aio_requests_mutex); ++ for (i = 0; i < ret; i++) ++ { ++ void (*cb)(kctx_t, struct kiocb *, long, long); ++ ++ cb = (void *) (uintptr_t) ev[i].kioe_data; ++ cb (kctx, (struct kiocb *) (uintptr_t) ev[i].kioe_obj, ++ ev[i].kioe_res, ev[i].kioe_res2); ++ } ++ if (ret < 10) ++ return 0; ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ timespec = &ts; ++ } ++ while (1); ++ ++ pthread_mutex_lock (&__aio_requests_mutex); ++ return (timespec != &ts ++ && INTERNAL_SYSCALL_ERROR_P (ret, err) ++ && INTERNAL_SYSCALL_ERRNO (ret, err) == ETIMEDOUT) ? ETIMEDOUT : 0; ++} ++ ++int ++internal_function ++__aio_create_kernel_thread (void) ++{ ++ pthread_t thid; ++ ++ if (__kernel_thread_started) ++ return 0; ++ ++ if (aio_create_helper_thread (&thid, handle_kernel_aio, NULL) != 0) ++ return -1; ++ __kernel_thread_started = 1; ++ return 0; ++} ++ ++static void * ++handle_kernel_aio (void *arg __attribute__((unused))) ++{ ++ int ret, i; ++ INTERNAL_SYSCALL_DECL (err); ++ struct kio_event ev[10]; ++ ++ for (;;) ++ { ++ ret = INTERNAL_SYSCALL (io_getevents, err, 5, __aio_kioctx, 1, 10, ev, ++ NULL); ++ if (INTERNAL_SYSCALL_ERROR_P (ret, err) || ret == 0) ++ continue; ++ pthread_mutex_lock (&__aio_requests_mutex); ++ for (i = 0; i < ret; i++) ++ { ++ void (*cb)(kctx_t, struct kiocb *, long, long); ++ ++ cb = (void *) (uintptr_t) ev[i].kioe_data; ++ cb (__aio_kioctx, (struct kiocb *) (uintptr_t) ev[i].kioe_obj, ++ ev[i].kioe_res, ev[i].kioe_res2); ++ } ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ } ++ return NULL; ++} ++ ++static int ++internal_function ++add_request_to_list (struct requestlist *newp, int fildes, int prio) ++{ ++ struct requestlist *last, *runp, *reqs; ++ ++ last = NULL; ++ reqs = newp->kioctx != KCTX_NONE ? krequests : requests; ++ runp = reqs; ++ ++ /* First look whether the current file descriptor is currently ++ worked with. */ ++ while (runp != NULL ++ && runp->aiocbp->aiocb.aio_fildes < fildes) ++ { ++ last = runp; ++ runp = runp->next_fd; ++ } ++ ++ if (runp != NULL ++ && runp->aiocbp->aiocb.aio_fildes == fildes) ++ { ++ /* The current file descriptor is worked on. It makes no sense ++ to start another thread since this new thread would fight ++ with the running thread for the resources. But we also cannot ++ say that the thread processing this desriptor shall immediately ++ after finishing the current job process this request if there ++ are other threads in the running queue which have a higher ++ priority. */ ++ ++ /* Simply enqueue it after the running one according to the ++ priority. */ ++ while (runp->next_prio != NULL ++ && runp->next_prio->aiocbp->aiocb.__abs_prio >= prio) ++ runp = runp->next_prio; ++ ++ newp->next_prio = runp->next_prio; ++ runp->next_prio = newp; ++ if (newp->kioctx != KCTX_NONE) ++ { ++ newp->prev_prio = runp; ++ if (newp->next_prio != NULL) ++ newp->next_prio->prev_prio = newp; ++ } ++ return queued; ++ } ++ else ++ { ++ /* Enqueue this request for a new descriptor. */ ++ if (last == NULL) ++ { ++ newp->last_fd = NULL; ++ newp->next_fd = reqs; ++ if (reqs != NULL) ++ reqs->last_fd = newp; ++ if (newp->kioctx != KCTX_NONE) ++ krequests = newp; ++ else ++ requests = newp; ++ } ++ else ++ { ++ newp->next_fd = last->next_fd; ++ newp->last_fd = last; ++ last->next_fd = newp; ++ if (newp->next_fd != NULL) ++ newp->next_fd->last_fd = newp; ++ } ++ ++ newp->next_prio = NULL; ++ if (newp->kioctx != KCTX_NONE) ++ newp->prev_prio = NULL; ++ return yes; ++ } ++} ++ ++static int ++internal_function ++__aio_enqueue_user_request (struct requestlist *newp) ++{ ++ int result = 0; ++ int running = add_request_to_list (newp, newp->aiocbp->aiocb.aio_fildes, ++ newp->aiocbp->aiocb.__abs_prio); ++ ++ if (running == yes) ++ { ++ /* We try to create a new thread for this file descriptor. The ++ function which gets called will handle all available requests ++ for this descriptor and when all are processed it will ++ terminate. ++ ++ If no new thread can be created or if the specified limit of ++ threads for AIO is reached we queue the request. */ ++ ++ /* See if we need to and are able to create a thread. */ ++ if (nthreads < optim.aio_threads && idle_thread_count == 0) ++ { ++ pthread_t thid; ++ ++ running = newp->running = allocated; ++ ++ /* Now try to start a thread. */ ++ result = aio_create_helper_thread (&thid, handle_fildes_io, newp); ++ if (result == 0) ++ /* We managed to enqueue the request. All errors which can ++ happen now can be recognized by calls to `aio_return' and ++ `aio_error'. */ ++ ++nthreads; ++ else ++ { ++ /* Reset the running flag. The new request is not running. */ ++ running = newp->running = yes; ++ ++ if (nthreads == 0) ++ { ++ /* We cannot create a thread in the moment and there is ++ also no thread running. This is a problem. `errno' is ++ set to EAGAIN if this is only a temporary problem. */ ++ __aio_remove_request (NULL, newp, 0); ++ } ++ else ++ result = 0; ++ } ++ } ++ } ++ ++ /* Enqueue the request in the run queue if it is not yet running. */ ++ if (running == yes && result == 0) ++ { ++ add_request_to_runlist (newp); ++ ++ /* If there is a thread waiting for work, then let it know that we ++ have just given it something to do. */ ++ if (idle_thread_count > 0) ++ pthread_cond_signal (&__aio_new_request_notification); ++ } ++ ++ if (result == 0) ++ newp->running = running; ++ return result; ++} ++ ++/* The main function of the async I/O handling. It enqueues requests ++ and if necessary starts and handles threads. */ ++struct requestlist * ++internal_function ++__aio_enqueue_request_ctx (aiocb_union *aiocbp, int operation, kctx_t kctx) ++{ ++ int policy, prio, result; ++ struct sched_param param; ++ struct requestlist *newp; ++ int op = (operation & 0xffff); ++ ++ if (op == LIO_SYNC || op == LIO_DSYNC) ++ { ++ aiocbp->aiocb.aio_reqprio = 0; ++ /* FIXME: Kernel doesn't support sync yet. */ ++ operation &= ~LIO_KTHREAD; ++ kctx = KCTX_NONE; ++ } ++ else if (aiocbp->aiocb.aio_reqprio < 0 ++ || aiocbp->aiocb.aio_reqprio > AIO_PRIO_DELTA_MAX) ++ { ++ /* Invalid priority value. */ ++ __set_errno (EINVAL); ++ aiocbp->aiocb.__error_code = EINVAL; ++ aiocbp->aiocb.__return_value = -1; ++ return NULL; ++ } ++ ++ if ((operation & LIO_KTHREAD) || kctx != KCTX_NONE) ++ { ++ /* io_* is only really asynchronous for O_DIRECT or /dev/raw*. */ ++ int fl = __fcntl (aiocbp->aiocb.aio_fildes, F_GETFL); ++ if (fl < 0 || (fl & O_DIRECT) == 0) ++ { ++ struct stat64 st; ++ if (__fxstat64 (_STAT_VER, aiocbp->aiocb.aio_fildes, &st) < 0 ++ || ! S_ISCHR (st.st_mode) ++ || major (st.st_rdev) != 162) ++ { ++ operation &= ~LIO_KTHREAD; ++ kctx = KCTX_NONE; ++ } ++ } ++ } ++ ++ /* Compute priority for this request. */ ++ pthread_getschedparam (pthread_self (), &policy, ¶m); ++ prio = param.sched_priority - aiocbp->aiocb.aio_reqprio; ++ ++ /* Get the mutex. */ ++ pthread_mutex_lock (&__aio_requests_mutex); ++ ++ if (operation & LIO_KTHREAD) ++ { ++ if (__aio_kioctx == KCTX_NONE && !__have_no_kernel_aio) ++ { ++ int res; ++ INTERNAL_SYSCALL_DECL (err); ++ ++ __aio_kioctx = 0; ++ do ++ res = INTERNAL_SYSCALL (io_setup, err, 2, 1024, &__aio_kioctx); ++ while (INTERNAL_SYSCALL_ERROR_P (res, err) ++ && INTERNAL_SYSCALL_ERRNO (res, err) == EINTR); ++ if (INTERNAL_SYSCALL_ERROR_P (res, err)) ++ { ++ __have_no_kernel_aio = 1; ++ __aio_kioctx = KCTX_NONE; ++ } ++ } ++ ++ kctx = __aio_kioctx; ++ ++ if (kctx != KCTX_NONE && !__kernel_thread_started ++ && ((operation & LIO_KTHREAD_REQUIRED) ++ || aiocbp->aiocb.aio_sigevent.sigev_notify != SIGEV_NONE)) ++ { ++ if (__aio_create_kernel_thread () < 0) ++ kctx = KCTX_NONE; ++ } ++ } ++ ++ /* Get a new element for the waiting list. */ ++ newp = get_elem (); ++ if (newp == NULL) ++ { ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ __set_errno (EAGAIN); ++ return NULL; ++ } ++ newp->aiocbp = aiocbp; ++#ifdef BROKEN_THREAD_SIGNALS ++ newp->caller_pid = (aiocbp->aiocb.aio_sigevent.sigev_notify == SIGEV_SIGNAL ++ ? getpid () : 0); ++#endif ++ newp->waiting = NULL; ++ newp->kioctx = kctx; ++ ++ aiocbp->aiocb.__abs_prio = prio; ++ aiocbp->aiocb.__policy = policy; ++ aiocbp->aiocb.aio_lio_opcode = op; ++ aiocbp->aiocb.__error_code = EINPROGRESS; ++ aiocbp->aiocb.__return_value = 0; ++ ++ if (newp->kioctx != KCTX_NONE) ++ { ++ int res; ++ INTERNAL_SYSCALL_DECL (err); ++ ++ aiocb_union *aiocbp = newp->aiocbp; ++ struct kiocb *kiocbs[] __attribute__((unused)) = { &newp->kiocb }; ++ ++ newp->kiocb.kiocb_data = (uintptr_t) kernel_callback; ++ switch (op & 127) ++ { ++ case LIO_READ: newp->kiocb.kiocb_lio_opcode = IO_CMD_PREAD; break; ++ case LIO_WRITE: newp->kiocb.kiocb_lio_opcode = IO_CMD_PWRITE; break; ++ case LIO_SYNC: ++ case LIO_DSYNC: newp->kiocb.kiocb_lio_opcode = IO_CMD_FSYNC; break; ++ } ++ if (op & 128) ++ newp->kiocb.kiocb_offset = aiocbp->aiocb64.aio_offset; ++ else ++ newp->kiocb.kiocb_offset = aiocbp->aiocb.aio_offset; ++ newp->kiocb.kiocb_fildes = aiocbp->aiocb.aio_fildes; ++ newp->kiocb.kiocb_buf = (uintptr_t) aiocbp->aiocb.aio_buf; ++ newp->kiocb.kiocb_nbytes = aiocbp->aiocb.aio_nbytes; ++ /* FIXME. */ ++ newp->kiocb.kiocb_req_prio = 0; ++ res = INTERNAL_SYSCALL (io_submit, err, 3, newp->kioctx, 1, kiocbs); ++ if (! INTERNAL_SYSCALL_ERROR_P (res, err)) ++ { ++ newp->running = allocated; ++ add_request_to_list (newp, aiocbp->aiocb.aio_fildes, prio); ++ /* Release the mutex. */ ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ return newp; ++ } ++ newp->kioctx = KCTX_NONE; ++ } ++ ++ result = __aio_enqueue_user_request (newp); ++ if (result) ++ { ++ /* Something went wrong. */ ++ __aio_free_request (newp); ++ aiocbp->aiocb.__error_code = result; ++ __set_errno (result); ++ newp = NULL; ++ } ++ ++ /* Release the mutex. */ ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ ++ return newp; ++} ++ ++ ++static int ++wait_for_kernel_requests (int fildes) ++{ ++ pthread_mutex_lock (&__aio_requests_mutex); ++ ++ struct requestlist *kreq = __aio_find_kreq_fd (fildes), *req; ++ int nent = 0; ++ int ret = 0; ++ ++ req = kreq; ++ while (req) ++ { ++ if (req->running == allocated) ++ ++nent; ++ req = req->next_prio; ++ } ++ ++ if (nent) ++ { ++ if (__aio_create_kernel_thread () < 0) ++ { ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ return -1; ++ } ++ ++#ifndef DONT_NEED_AIO_MISC_COND ++ pthread_cond_t cond = PTHREAD_COND_INITIALIZER; ++#endif ++ struct waitlist waitlist[nent]; ++ int cnt = 0; ++ ++ while (kreq) ++ { ++ if (kreq->running == allocated) ++ { ++#ifndef DONT_NEED_AIO_MISC_COND ++ waitlist[cnt].cond = &cond; ++#endif ++ waitlist[cnt].result = NULL; ++ waitlist[cnt].next = kreq->waiting; ++ waitlist[cnt].counterp = &nent; ++ waitlist[cnt].sigevp = NULL; ++#ifdef BROKEN_THREAD_SIGNALS ++ waitlist[cnt].caller_pid = 0; /* Not needed. */ ++#endif ++ kreq->waiting = &waitlist[cnt++]; ++ } ++ kreq = kreq->next_prio; ++ } ++ ++#ifdef DONT_NEED_AIO_MISC_COND ++ AIO_MISC_WAIT (ret, nent, NULL, 0); ++#else ++ do ++ pthread_cond_wait (&cond, &__aio_requests_mutex); ++ while (nent); ++ ++ pthread_cond_destroy (&cond); ++#endif ++ } ++ ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ return ret; ++} ++ ++ ++static void * ++handle_fildes_io (void *arg) ++{ ++ pthread_t self = pthread_self (); ++ struct sched_param param; ++ struct requestlist *runp = (struct requestlist *) arg; ++ aiocb_union *aiocbp; ++ int policy; ++ int fildes; ++ ++ pthread_getschedparam (self, &policy, ¶m); ++ ++ do ++ { ++ /* If runp is NULL, then we were created to service the work queue ++ in general, not to handle any particular request. In that case we ++ skip the "do work" stuff on the first pass, and go directly to the ++ "get work off the work queue" part of this loop, which is near the ++ end. */ ++ if (runp == NULL) ++ pthread_mutex_lock (&__aio_requests_mutex); ++ else ++ { ++ /* Hopefully this request is marked as running. */ ++ assert (runp->running == allocated); ++ ++ /* Update our variables. */ ++ aiocbp = runp->aiocbp; ++ fildes = aiocbp->aiocb.aio_fildes; ++ ++ /* Change the priority to the requested value (if necessary). */ ++ if (aiocbp->aiocb.__abs_prio != param.sched_priority ++ || aiocbp->aiocb.__policy != policy) ++ { ++ param.sched_priority = aiocbp->aiocb.__abs_prio; ++ policy = aiocbp->aiocb.__policy; ++ pthread_setschedparam (self, policy, ¶m); ++ } ++ ++ /* Process request pointed to by RUNP. We must not be disturbed ++ by signals. */ ++ if ((aiocbp->aiocb.aio_lio_opcode & 127) == LIO_READ) ++ { ++ if (aiocbp->aiocb.aio_lio_opcode & 128) ++ aiocbp->aiocb.__return_value = ++ TEMP_FAILURE_RETRY (__pread64 (fildes, (void *) ++ aiocbp->aiocb64.aio_buf, ++ aiocbp->aiocb64.aio_nbytes, ++ aiocbp->aiocb64.aio_offset)); ++ else ++ aiocbp->aiocb.__return_value = ++ TEMP_FAILURE_RETRY (pread (fildes, ++ (void *) aiocbp->aiocb.aio_buf, ++ aiocbp->aiocb.aio_nbytes, ++ aiocbp->aiocb.aio_offset)); ++ ++ if (aiocbp->aiocb.__return_value == -1 && errno == ESPIPE) ++ /* The Linux kernel is different from others. It returns ++ ESPIPE if using pread on a socket. Other platforms ++ simply ignore the offset parameter and behave like ++ read. */ ++ aiocbp->aiocb.__return_value = ++ TEMP_FAILURE_RETRY (read (fildes, ++ (void *) aiocbp->aiocb64.aio_buf, ++ aiocbp->aiocb64.aio_nbytes)); ++ } ++ else if ((aiocbp->aiocb.aio_lio_opcode & 127) == LIO_WRITE) ++ { ++ if (aiocbp->aiocb.aio_lio_opcode & 128) ++ aiocbp->aiocb.__return_value = ++ TEMP_FAILURE_RETRY (__pwrite64 (fildes, (const void *) ++ aiocbp->aiocb64.aio_buf, ++ aiocbp->aiocb64.aio_nbytes, ++ aiocbp->aiocb64.aio_offset)); ++ else ++ aiocbp->aiocb.__return_value = ++ TEMP_FAILURE_RETRY (__libc_pwrite (fildes, (const void *) ++ aiocbp->aiocb.aio_buf, ++ aiocbp->aiocb.aio_nbytes, ++ aiocbp->aiocb.aio_offset)); ++ ++ if (aiocbp->aiocb.__return_value == -1 && errno == ESPIPE) ++ /* The Linux kernel is different from others. It returns ++ ESPIPE if using pwrite on a socket. Other platforms ++ simply ignore the offset parameter and behave like ++ write. */ ++ aiocbp->aiocb.__return_value = ++ TEMP_FAILURE_RETRY (write (fildes, ++ (void *) aiocbp->aiocb64.aio_buf, ++ aiocbp->aiocb64.aio_nbytes)); ++ } ++ else if (aiocbp->aiocb.aio_lio_opcode == LIO_DSYNC ++ || aiocbp->aiocb.aio_lio_opcode == LIO_SYNC) ++ { ++ if (wait_for_kernel_requests (fildes) < 0) ++ { ++ aiocbp->aiocb.__return_value = -1; ++ __set_errno (ENOMEM); ++ } ++ else if (aiocbp->aiocb.aio_lio_opcode == LIO_DSYNC) ++ aiocbp->aiocb.__return_value = ++ TEMP_FAILURE_RETRY (fdatasync (fildes)); ++ else ++ aiocbp->aiocb.__return_value = ++ TEMP_FAILURE_RETRY (fsync (fildes)); ++ } ++ else ++ { ++ /* This is an invalid opcode. */ ++ aiocbp->aiocb.__return_value = -1; ++ __set_errno (EINVAL); ++ } ++ ++ /* Get the mutex. */ ++ pthread_mutex_lock (&__aio_requests_mutex); ++ ++ /* In theory we would need here a write memory barrier since the ++ callers test using aio_error() whether the request finished ++ and once this value != EINPROGRESS the field __return_value ++ must be committed to memory. ++ ++ But since the pthread_mutex_lock call involves write memory ++ barriers as well it is not necessary. */ ++ ++ if (aiocbp->aiocb.__return_value == -1) ++ aiocbp->aiocb.__error_code = errno; ++ else ++ aiocbp->aiocb.__error_code = 0; ++ ++ /* Send the signal to notify about finished processing of the ++ request. */ ++ __aio_notify (runp); ++ ++ /* For debugging purposes we reset the running flag of the ++ finished request. */ ++ assert (runp->running == allocated); ++ runp->running = done; ++ ++ /* Now dequeue the current request. */ ++ __aio_remove_request (NULL, runp, 0); ++ if (runp->next_prio != NULL) ++ add_request_to_runlist (runp->next_prio); ++ ++ /* Free the old element. */ ++ __aio_free_request (runp); ++ } ++ ++ runp = runlist; ++ ++ /* If the runlist is empty, then we sleep for a while, waiting for ++ something to arrive in it. */ ++ if (runp == NULL && optim.aio_idle_time >= 0) ++ { ++ struct timeval now; ++ struct timespec wakeup_time; ++ ++ ++idle_thread_count; ++ gettimeofday (&now, NULL); ++ wakeup_time.tv_sec = now.tv_sec + optim.aio_idle_time; ++ wakeup_time.tv_nsec = now.tv_usec * 1000; ++ if (wakeup_time.tv_nsec > 1000000000) ++ { ++ wakeup_time.tv_nsec -= 1000000000; ++ ++wakeup_time.tv_sec; ++ } ++ pthread_cond_timedwait (&__aio_new_request_notification, ++ &__aio_requests_mutex, ++ &wakeup_time); ++ --idle_thread_count; ++ runp = runlist; ++ } ++ ++ if (runp == NULL) ++ --nthreads; ++ else ++ { ++ assert (runp->running == yes); ++ runp->running = allocated; ++ runlist = runp->next_run; ++ ++ /* If we have a request to process, and there's still another in ++ the run list, then we need to either wake up or create a new ++ thread to service the request that is still in the run list. */ ++ if (runlist != NULL) ++ { ++ /* There are at least two items in the work queue to work on. ++ If there are other idle threads, then we should wake them ++ up for these other work elements; otherwise, we should try ++ to create a new thread. */ ++ if (idle_thread_count > 0) ++ pthread_cond_signal (&__aio_new_request_notification); ++ else if (nthreads < optim.aio_threads) ++ { ++ pthread_t thid; ++ ++ /* Now try to start a thread. If we fail, no big deal, ++ because we know that there is at least one thread (us) ++ that is working on AIO operations. */ ++ if (aio_create_helper_thread (&thid, handle_fildes_io, NULL) ++ == 0) ++ ++nthreads; ++ } ++ } ++ } ++ ++ /* Release the mutex. */ ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ } ++ while (runp != NULL); ++ ++ return NULL; ++} ++ ++ ++/* Free allocated resources. */ ++libc_freeres_fn (free_res) ++{ ++ size_t row; ++ ++ for (row = 0; row < pool_max_size; ++row) ++ free (pool[row]); ++ ++ free (pool); ++} ++ ++ ++/* Add newrequest to the runlist. The __abs_prio flag of newrequest must ++ be correctly set to do this. Also, you had better set newrequest's ++ "running" flag to "yes" before you release your lock or you'll throw an ++ assertion. */ ++static void ++internal_function ++add_request_to_runlist (struct requestlist *newrequest) ++{ ++ int prio = newrequest->aiocbp->aiocb.__abs_prio; ++ struct requestlist *runp; ++ ++ if (runlist == NULL || runlist->aiocbp->aiocb.__abs_prio < prio) ++ { ++ newrequest->next_run = runlist; ++ runlist = newrequest; ++ } ++ else ++ { ++ runp = runlist; ++ ++ while (runp->next_run != NULL ++ && runp->next_run->aiocbp->aiocb.__abs_prio >= prio) ++ runp = runp->next_run; ++ ++ newrequest->next_run = runp->next_run; ++ runp->next_run = newrequest; ++ } ++} ++#endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.h glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.h +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.h 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.h 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,329 @@ ++/* Copyright (C) 1997,1999,2000,2001,2002,2003,2006 ++ 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, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#ifndef _AIO_MISC_H ++ ++#include ++ ++#if !defined __NR_io_setup || !defined __NR_io_destroy \ ++ || !defined __NR_io_getevents || !defined __NR_io_submit \ ++ || !defined __NR_io_cancel ++ ++#include ++ ++#else ++ ++#define _AIO_MISC_H 1 ++#define USE_KAIO 1 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef HAVE_FORCED_UNWIND ++ ++/* We define a special synchronization primitive for AIO. POSIX ++ conditional variables would be ideal but the pthread_cond_*wait ++ operations do not return on EINTR. This is a requirement for ++ correct aio_suspend and lio_listio implementations. */ ++ ++#include ++#include ++#include ++ ++# define DONT_NEED_AIO_MISC_COND 1 ++ ++# define AIO_MISC_NOTIFY(waitlist) \ ++ do { \ ++ if (*waitlist->counterp > 0 && --*waitlist->counterp == 0) \ ++ lll_futex_wake (waitlist->counterp, 1, LLL_PRIVATE); \ ++ } while (0) ++ ++# define AIO_MISC_WAIT(result, futex, timeout, cancel) \ ++ do { \ ++ volatile int *futexaddr = &futex; \ ++ int oldval = futex; \ ++ \ ++ if (oldval != 0) \ ++ { \ ++ pthread_mutex_unlock (&__aio_requests_mutex); \ ++ \ ++ int oldtype; \ ++ if (cancel) \ ++ oldtype = LIBC_CANCEL_ASYNC (); \ ++ \ ++ int status; \ ++ do \ ++ { \ ++ status = lll_futex_timed_wait (futexaddr, oldval, timeout, \ ++ LLL_PRIVATE); \ ++ if (status != -EWOULDBLOCK) \ ++ break; \ ++ \ ++ oldval = *futexaddr; \ ++ } \ ++ while (oldval != 0); \ ++ \ ++ if (cancel) \ ++ LIBC_CANCEL_RESET (oldtype); \ ++ \ ++ if (status == -EINTR) \ ++ result = EINTR; \ ++ else if (status == -ETIMEDOUT) \ ++ result = EAGAIN; \ ++ else \ ++ assert (status == 0 || status == -EWOULDBLOCK); \ ++ \ ++ pthread_mutex_lock (&__aio_requests_mutex); \ ++ } \ ++ } while (0) ++ ++#endif ++ ++typedef unsigned long kctx_t; ++#define KCTX_NONE ~0UL ++extern kctx_t __aio_kioctx; ++ ++enum ++{ ++ IO_CMD_PREAD, ++ IO_CMD_PWRITE, ++ IO_CMD_FSYNC, ++ IO_CMD_FDSYNC, ++ IO_CMD_PREADX, ++ IO_CMD_POLL ++}; ++ ++struct kiocb ++{ ++ uint64_t kiocb_data; ++ uint64_t kiocb_key; ++ uint16_t kiocb_lio_opcode; ++ int16_t kiocb_req_prio; ++ uint32_t kiocb_fildes; ++ uint64_t kiocb_buf; ++ uint64_t kiocb_nbytes; ++ int64_t kiocb_offset; ++ int64_t __pad3, __pad4; ++}; ++ ++struct kio_event ++{ ++ uint64_t kioe_data; ++ uint64_t kioe_obj; ++ int64_t kioe_res; ++ int64_t kioe_res2; ++}; ++ ++/* Extend the operation enum. */ ++enum ++{ ++ LIO_DSYNC = LIO_NOP + 1, ++ LIO_SYNC, ++ LIO_READ64 = LIO_READ | 128, ++ LIO_WRITE64 = LIO_WRITE | 128, ++ LIO_KTHREAD = 0x10000, ++ LIO_KTHREAD_REQUIRED = 0x20000 ++}; ++ ++ ++/* Union of the two request types. */ ++typedef union ++ { ++ struct aiocb aiocb; ++ struct aiocb64 aiocb64; ++ } aiocb_union; ++ ++ ++/* Used to synchronize. */ ++struct waitlist ++ { ++ struct waitlist *next; ++ ++ /* The next two fields is used in synchronous io_listio' operations. */ ++#ifndef DONT_NEED_AIO_MISC_COND ++ pthread_cond_t *cond; ++#endif ++ int *result; ++ ++ volatile int *counterp; ++ /* The next field is used in asynchronous `lio_listio' operations. */ ++ struct sigevent *sigevp; ++#ifdef BROKEN_THREAD_SIGNALS ++ /* XXX See requestlist, it's used to work around the broken signal ++ handling in Linux. */ ++ pid_t caller_pid; ++#endif ++ }; ++ ++ ++/* Status of a request. */ ++enum ++{ ++ no, ++ queued, ++ yes, ++ allocated, ++ done ++}; ++ ++ ++/* Used to queue requests.. */ ++struct requestlist ++ { ++ struct kiocb kiocb; ++ kctx_t kioctx; ++ ++ int running; ++ ++ struct requestlist *last_fd; ++ struct requestlist *next_fd; ++ struct requestlist *next_prio; ++ struct requestlist *next_run; ++ /* For kioctx != KCTX_NONE requests we are doubly linked. */ ++#define prev_prio next_run ++ ++ /* Pointer to the actual data. */ ++ aiocb_union *aiocbp; ++ ++#ifdef BROKEN_THREAD_SIGNALS ++ /* PID of the initiator thread. ++ XXX This is only necessary for the broken signal handling on Linux. */ ++ pid_t caller_pid; ++#endif ++ ++ /* List of waiting processes. */ ++ struct waitlist *waiting; ++ }; ++ ++ ++/* Lock for global I/O list of requests. */ ++extern pthread_mutex_t __aio_requests_mutex attribute_hidden; ++ ++ ++/* Enqueue request. */ ++extern struct requestlist *__aio_enqueue_request_ctx (aiocb_union *aiocbp, ++ int operation, ++ kctx_t kctx) ++ attribute_hidden internal_function; ++ ++#define __aio_enqueue_request(aiocbp, operation) \ ++ __aio_enqueue_request_ctx (aiocbp, operation | LIO_KTHREAD, KCTX_NONE) ++ ++/* Find request entry for given AIO control block. */ ++extern struct requestlist *__aio_find_req (aiocb_union *elem) ++ attribute_hidden internal_function; ++ ++/* Find request entry for given file descriptor. */ ++extern struct requestlist *__aio_find_req_fd (int fildes) ++ attribute_hidden internal_function; ++ ++/* Find request entry for given file descriptor. */ ++extern struct requestlist *__aio_find_kreq_fd (int fildes) ++ attribute_hidden internal_function; ++ ++/* Remove request from the list. */ ++extern void __aio_remove_request (struct requestlist *last, ++ struct requestlist *req, int all) ++ attribute_hidden internal_function; ++ ++extern void __aio_remove_krequest (struct requestlist *req) ++ attribute_hidden internal_function; ++ ++/* Release the entry for the request. */ ++extern void __aio_free_request (struct requestlist *req) ++ attribute_hidden internal_function; ++ ++/* Notify initiator of request and tell this everybody listening. */ ++extern void __aio_notify (struct requestlist *req) ++ attribute_hidden internal_function; ++ ++/* Notify initiator of request. */ ++#ifdef BROKEN_THREAD_SIGNALS ++extern int __aio_notify_only (struct sigevent *sigev, pid_t caller_pid) ++ attribute_hidden internal_function; ++#else ++extern int __aio_notify_only (struct sigevent *sigev) ++ attribute_hidden internal_function; ++#endif ++ ++/* Send the signal. */ ++extern int __aio_sigqueue (int sig, const union sigval val, pid_t caller_pid) ++ attribute_hidden internal_function; ++ ++extern int __aio_wait_for_events (kctx_t kctx, const struct timespec *timeout) ++ attribute_hidden internal_function; ++ ++extern void __aio_read_one_event (void) attribute_hidden internal_function; ++ ++extern int __aio_create_kernel_thread (void) ++ attribute_hidden internal_function; ++ ++extern int __have_no_kernel_aio attribute_hidden; ++extern int __kernel_thread_started attribute_hidden; ++ ++#ifndef BROKEN_THREAD_SIGNALS ++# define aio_start_notify_thread __aio_start_notify_thread ++# define aio_create_helper_thread __aio_create_helper_thread ++ ++extern inline void ++__aio_start_notify_thread (void) ++{ ++ sigset_t ss; ++ sigemptyset (&ss); ++ INTERNAL_SYSCALL_DECL (err); ++ INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, NULL, _NSIG / 8); ++} ++ ++extern inline int ++__aio_create_helper_thread (pthread_t *threadp, void *(*tf) (void *), void *arg) ++{ ++ pthread_attr_t attr; ++ ++ /* Make sure the thread is created detached. */ ++ pthread_attr_init (&attr); ++ pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); ++ ++ /* The helper thread needs only very little resources. */ ++ (void) pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN); ++ ++ /* Block all signals in the helper thread. To do this thoroughly we ++ temporarily have to block all signals here. */ ++ sigset_t ss; ++ sigset_t oss; ++ sigfillset (&ss); ++ INTERNAL_SYSCALL_DECL (err); ++ INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, &oss, _NSIG / 8); ++ ++ int ret = pthread_create (threadp, &attr, tf, arg); ++ ++ /* Restore the signal mask. */ ++ INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &oss, NULL, ++ _NSIG / 8); ++ ++ (void) pthread_attr_destroy (&attr); ++ return ret; ++} ++#endif ++ ++#endif ++#endif /* aio_misc.h */ +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_notify.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_notify.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_notify.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_notify.c 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,2 @@ ++#include ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_read64.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_read64.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_read64.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_read64.c 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,2 @@ ++#include ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_read.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_read.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_read.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_read.c 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,4 @@ ++#define aio_read64 __renamed_aio_read64 ++#include ++#undef aio_read64 ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_return.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_return.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_return.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_return.c 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,50 @@ ++/* Return exit value of asynchronous I/O request. ++ Copyright (C) 1997, 2002, 2003 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 1997. ++ ++ 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. */ ++ ++ ++/* We use an UGLY hack to prevent gcc from finding us cheating. The ++ implementation of aio_return and aio_return64 are identical and so ++ we want to avoid code duplication by using aliases. But gcc sees ++ the different parameter lists and prints a warning. We define here ++ a function so that aio_return64 has no prototype. */ ++#define aio_return64 XXX ++#include ++/* And undo the hack. */ ++#undef aio_return64 ++ ++#include ++ ++#ifndef USE_KAIO ++#include ++#else ++ ++#include ++ ++ssize_t ++aio_return (aiocbp) ++ struct aiocb *aiocbp; ++{ ++ if (aiocbp->__error_code == EINPROGRESS) ++ __aio_read_one_event (); ++ return aiocbp->__return_value; ++} ++ ++weak_alias (aio_return, aio_return64) ++#endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_sigqueue.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_sigqueue.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_sigqueue.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_sigqueue.c 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,2 @@ ++#include ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_suspend.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_suspend.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_suspend.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_suspend.c 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,327 @@ ++/* Suspend until termination of a requests. ++ Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2006 ++ Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 1997. ++ ++ 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. */ ++ ++ ++/* We use an UGLY hack to prevent gcc from finding us cheating. The ++ implementations of aio_suspend and aio_suspend64 are identical and so ++ we want to avoid code duplication by using aliases. But gcc sees ++ the different parameter lists and prints a warning. We define here ++ a function so that aio_suspend64 has no prototype. */ ++#define aio_suspend64 XXX ++#include ++/* And undo the hack. */ ++#undef aio_suspend64 ++ ++#include ++ ++#ifndef USE_KAIO ++#include ++#else ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++ ++struct clparam ++{ ++ const struct aiocb *const *list; ++ struct waitlist *waitlist; ++ struct requestlist **requestlist; ++#ifndef DONT_NEED_AIO_MISC_COND ++ pthread_cond_t *cond; ++#endif ++ int nent; ++}; ++ ++ ++static void ++cleanup (void *arg) ++{ ++#ifdef DONT_NEED_AIO_MISC_COND ++ /* Acquire the mutex. If pthread_cond_*wait is used this would ++ happen implicitly. */ ++ pthread_mutex_lock (&__aio_requests_mutex); ++#endif ++ ++ const struct clparam *param = (const struct clparam *) arg; ++ ++ /* Now remove the entry in the waiting list for all requests ++ which didn't terminate. */ ++ int cnt = param->nent; ++ while (cnt-- > 0) ++ if (param->list[cnt] != NULL ++ && param->list[cnt]->__error_code == EINPROGRESS) ++ { ++ struct waitlist **listp; ++ ++ assert (param->requestlist[cnt] != NULL); ++ ++ /* There is the chance that we cannot find our entry anymore. This ++ could happen if the request terminated and restarted again. */ ++ listp = ¶m->requestlist[cnt]->waiting; ++ while (*listp != NULL && *listp != ¶m->waitlist[cnt]) ++ listp = &(*listp)->next; ++ ++ if (*listp != NULL) ++ *listp = (*listp)->next; ++ } ++ ++#ifndef DONT_NEED_AIO_MISC_COND ++ /* Release the conditional variable. */ ++ (void) pthread_cond_destroy (param->cond); ++#endif ++ ++ /* Release the mutex. */ ++ pthread_mutex_unlock (&__aio_requests_mutex); ++} ++ ++ ++int ++aio_suspend (list, nent, timeout) ++ const struct aiocb *const list[]; ++ int nent; ++ const struct timespec *timeout; ++{ ++ if (__builtin_expect (nent < 0, 0)) ++ { ++ __set_errno (EINVAL); ++ return -1; ++ } ++ ++ struct waitlist waitlist[nent]; ++ struct requestlist *requestlist[nent]; ++#ifndef DONT_NEED_AIO_MISC_COND ++ pthread_cond_t cond = PTHREAD_COND_INITIALIZER; ++#endif ++ int cnt; ++ int result = 0; ++ int cntr = 1; ++ int total = 0, ktotal = 0; ++ ++ /* Request the mutex. */ ++ pthread_mutex_lock (&__aio_requests_mutex); ++ ++ /* There is not yet a finished request. Signal the request that ++ we are working for it. */ ++ for (cnt = 0; cnt < nent; ++cnt) ++ if (list[cnt] != NULL) ++ { ++ if (list[cnt]->__error_code == EINPROGRESS) ++ { ++ requestlist[cnt] = __aio_find_req ((aiocb_union *) list[cnt]); ++ ++ if (requestlist[cnt] != NULL) ++ { ++#ifndef DONT_NEED_AIO_MISC_COND ++ waitlist[cnt].cond = &cond; ++#endif ++ waitlist[cnt].result = NULL; ++ waitlist[cnt].next = requestlist[cnt]->waiting; ++ waitlist[cnt].counterp = &cntr; ++ waitlist[cnt].sigevp = NULL; ++#ifdef BROKEN_THREAD_SIGNALS ++ waitlist[cnt].caller_pid = 0; /* Not needed. */ ++#endif ++ requestlist[cnt]->waiting = &waitlist[cnt]; ++ total++; ++ if (requestlist[cnt]->kioctx != KCTX_NONE) ++ ktotal++; ++ } ++ else ++ /* We will never suspend. */ ++ break; ++ } ++ else ++ /* We will never suspend. */ ++ break; ++ } ++ ++ ++ /* Only if none of the entries is NULL or finished to be wait. */ ++ if (cnt == nent && total) ++ { ++ struct clparam clparam = ++ { ++ .list = list, ++ .waitlist = waitlist, ++ .requestlist = requestlist, ++#ifndef DONT_NEED_AIO_MISC_COND ++ .cond = &cond, ++#endif ++ .nent = nent ++ }; ++ ++ pthread_cleanup_push (cleanup, &clparam); ++ ++ if (!__kernel_thread_started && ktotal) ++ { ++ /* If the kernel aio thread was not started yet all requests ++ are served by the kernel and there are no other threads running, ++ read events with mutex hold, so that nobody else can get them ++ instead of us here. */ ++ if (SINGLE_THREAD_P && total == ktotal) ++ { ++ if (timeout == NULL) ++ { ++ while (cntr == 1) ++ __aio_wait_for_events (__aio_kioctx, NULL); ++ } ++ else ++ { ++ struct timeval now; ++ struct timespec abstime, ts; ++ ++ __gettimeofday (&now, NULL); ++ abstime.tv_nsec = timeout->tv_nsec + now.tv_usec * 1000; ++ abstime.tv_sec = timeout->tv_sec + now.tv_sec; ++ if (abstime.tv_nsec >= 1000000000) ++ { ++ abstime.tv_nsec -= 1000000000; ++ abstime.tv_sec += 1; ++ } ++ ++ for (;;) ++ { ++ result = __aio_wait_for_events (__aio_kioctx, timeout); ++ if (cntr < 1) ++ break; ++ if (result == ETIMEDOUT) ++ break; ++ ++ __gettimeofday (&now, NULL); ++ if (now.tv_sec > abstime.tv_sec ++ || (now.tv_sec == abstime.tv_sec ++ && now.tv_usec * 1000 >= abstime.tv_nsec)) ++ break; ++ ++ ts.tv_nsec = abstime.tv_nsec - now.tv_usec * 1000; ++ ts.tv_sec = abstime.tv_sec - now.tv_sec; ++ if (abstime.tv_nsec < now.tv_usec * 1000) ++ { ++ ts.tv_nsec += 1000000000; ++ ts.tv_sec -= 1; ++ } ++ timeout = &ts; ++ } ++ ++ if (cntr < 1) ++ result = 0; ++ else ++ result = ETIMEDOUT; ++ } ++ total = 0; ++ } ++ else if (__aio_create_kernel_thread () < 0) ++ { ++ total = 0; ++ __set_errno (ENOMEM); ++ result = -1; ++ } ++ } ++ ++ if (total == 0) ++ /* Suspending was handled above. */ ++ ; ++#ifdef DONT_NEED_AIO_MISC_COND ++ else ++ AIO_MISC_WAIT (result, cntr, timeout, 1); ++#else ++ else if (timeout == NULL) ++ result = pthread_cond_wait (&cond, &__aio_requests_mutex); ++ else ++ { ++ /* We have to convert the relative timeout value into an ++ absolute time value with pthread_cond_timedwait expects. */ ++ struct timeval now; ++ struct timespec abstime; ++ ++ __gettimeofday (&now, NULL); ++ abstime.tv_nsec = timeout->tv_nsec + now.tv_usec * 1000; ++ abstime.tv_sec = timeout->tv_sec + now.tv_sec; ++ if (abstime.tv_nsec >= 1000000000) ++ { ++ abstime.tv_nsec -= 1000000000; ++ abstime.tv_sec += 1; ++ } ++ ++ result = pthread_cond_timedwait (&cond, &__aio_requests_mutex, ++ &abstime); ++ } ++#endif ++ ++ pthread_cleanup_pop (0); ++ } ++ ++ /* Now remove the entry in the waiting list for all requests ++ which didn't terminate. */ ++ while (cnt-- > 0) ++ if (list[cnt] != NULL && list[cnt]->__error_code == EINPROGRESS) ++ { ++ struct waitlist **listp; ++ ++ assert (requestlist[cnt] != NULL); ++ ++ /* There is the chance that we cannot find our entry anymore. This ++ could happen if the request terminated and restarted again. */ ++ listp = &requestlist[cnt]->waiting; ++ while (*listp != NULL && *listp != &waitlist[cnt]) ++ listp = &(*listp)->next; ++ ++ if (*listp != NULL) ++ *listp = (*listp)->next; ++ } ++ ++#ifndef DONT_NEED_AIO_MISC_COND ++ /* Release the conditional variable. */ ++ if (__builtin_expect (pthread_cond_destroy (&cond) != 0, 0)) ++ /* This must never happen. */ ++ abort (); ++#endif ++ ++ if (result != 0) ++ { ++#ifndef DONT_NEED_AIO_MISC_COND ++ /* An error occurred. Possibly it's ETIMEDOUT. We have to translate ++ the timeout error report of `pthread_cond_timedwait' to the ++ form expected from `aio_suspend'. */ ++ if (result == ETIMEDOUT) ++ __set_errno (EAGAIN); ++ else ++#endif ++ __set_errno (result); ++ ++ result = -1; ++ } ++ ++ /* Release the mutex. */ ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ ++ return result; ++} ++ ++weak_alias (aio_suspend, aio_suspend64) ++#endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_write64.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_write64.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_write64.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_write64.c 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,2 @@ ++#include ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_write.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_write.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/kaio_write.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/kaio_write.c 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,4 @@ ++#define aio_write64 __renamed_aio_write64 ++#include ++#undef aio_write64 ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/klio_listio64.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/klio_listio64.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/klio_listio64.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/klio_listio64.c 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,40 @@ ++/* Enqueue and list of read or write requests, 64bit offset version. ++ Copyright (C) 1997, 1998, 1999, 2003, 2006 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 1997. ++ ++ 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 ++ ++#ifndef USE_KAIO ++#include ++#else ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define lio_listio lio_listio64 ++#define __lio_listio_21 __lio_listio64_21 ++#define __lio_listio_item_notify __lio_listio64_item_notify ++#define aiocb aiocb64 ++#define LIO_OPCODE_BASE 128 ++#include ++ ++#endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/klio_listio.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/klio_listio.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/klio_listio.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/klio_listio.c 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,322 @@ ++/* Enqueue and list of read or write requests. ++ Copyright (C) 1997,1998,1999,2000,2001,2002,2003,2005,2006 ++ Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 1997. ++ ++ 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 ++ ++#ifndef USE_KAIO ++#include ++#else ++ ++#ifndef lio_listio ++#include ++#include ++#include ++#include ++#include ++ ++#define LIO_OPCODE_BASE 0 ++#endif ++ ++#include ++ ++ ++/* We need this special structure to handle asynchronous I/O. */ ++struct async_waitlist ++ { ++ int counter; ++ struct sigevent sigev; ++ struct waitlist list[0]; ++ }; ++ ++ ++/* The code in glibc 2.1 to glibc 2.4 issued only one event when all ++ requests submitted with lio_listio finished. The existing practice ++ is to issue events for the individual requests as well. This is ++ what the new code does. */ ++#if SHLIB_COMPAT (librt, GLIBC_2_1, GLIBC_2_4) ++# define LIO_MODE(mode) ((mode) & 127) ++# define NO_INDIVIDUAL_EVENT_P(mode) ((mode) & 128) ++#else ++# define LIO_MODE(mode) mode ++# define NO_INDIVIDUAL_EVENT_P(mode) 0 ++#endif ++ ++ ++static int ++lio_listio_internal (int mode, struct aiocb *const list[], int nent, ++ struct sigevent *sig) ++{ ++ struct sigevent defsigev; ++ struct requestlist *requests[nent]; ++ int cnt; ++ volatile int total = 0; ++ int result = 0, op = 0; ++ kctx_t kctx = KCTX_NONE; ++ ++ if (sig == NULL) ++ { ++ defsigev.sigev_notify = SIGEV_NONE; ++ sig = &defsigev; ++ } ++ ++ /* Request the mutex. */ ++ pthread_mutex_lock (&__aio_requests_mutex); ++ ++ if (LIO_MODE (mode) == LIO_WAIT && ! __have_no_kernel_aio && nent > 0) ++ { ++ int res; ++ INTERNAL_SYSCALL_DECL (err); ++ ++ kctx = 0; ++ do ++ res = INTERNAL_SYSCALL (io_setup, err, 2, nent, &kctx); ++ while (INTERNAL_SYSCALL_ERROR_P (res, err) ++ && INTERNAL_SYSCALL_ERRNO (res, err) == EINTR); ++ if (INTERNAL_SYSCALL_ERROR_P (res, err)) ++ { ++ kctx = KCTX_NONE; ++ if (INTERNAL_SYSCALL_ERRNO (res, err) == ENOSYS) ++ __have_no_kernel_aio = 1; ++ } ++ } ++ else if (LIO_MODE (mode) == LIO_NOWAIT) ++ { ++ op = LIO_KTHREAD; ++ if (sig->sigev_notify != SIGEV_NONE) ++ op = LIO_KTHREAD | LIO_KTHREAD_REQUIRED; ++ } ++ op |= LIO_OPCODE_BASE; ++ ++ /* Now we can enqueue all requests. Since we already acquired the ++ mutex the enqueue function need not do this. */ ++ for (cnt = 0; cnt < nent; ++cnt) ++ if (list[cnt] != NULL && list[cnt]->aio_lio_opcode != LIO_NOP) ++ { ++ if (NO_INDIVIDUAL_EVENT_P (mode)) ++ list[cnt]->aio_sigevent.sigev_notify = SIGEV_NONE; ++ requests[cnt] ++ = __aio_enqueue_request_ctx ((aiocb_union *) list[cnt], ++ list[cnt]->aio_lio_opcode | op, ++ kctx); ++ ++ if (requests[cnt] != NULL) ++ /* Successfully enqueued. */ ++ ++total; ++ else ++ /* Signal that we've seen an error. `errno' and the error code ++ of the aiocb will tell more. */ ++ result = -1; ++ } ++ else ++ requests[cnt] = NULL; ++ ++ if (total == 0) ++ { ++ /* We don't have anything to do except signalling if we work ++ asynchronously. */ ++ ++ if (kctx != KCTX_NONE) ++ { ++ INTERNAL_SYSCALL_DECL (err); ++ INTERNAL_SYSCALL (io_destroy, err, 1, kctx); ++ } ++ ++ /* Release the mutex. We do this before raising a signal since the ++ signal handler might do a `siglongjmp' and then the mutex is ++ locked forever. */ ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ ++ if (LIO_MODE (mode) == LIO_NOWAIT) ++ { ++#ifdef BROKEN_THREAD_SIGNALS ++ __aio_notify_only (sig, ++ sig->sigev_notify == SIGEV_SIGNAL ? getpid () : 0); ++#else ++ __aio_notify_only (sig); ++#endif ++ } ++ ++ return result; ++ } ++ else if (LIO_MODE (mode) == LIO_WAIT) ++ { ++#ifndef DONT_NEED_AIO_MISC_COND ++ pthread_cond_t cond = PTHREAD_COND_INITIALIZER; ++ int oldstate; ++#endif ++ struct waitlist waitlist[nent]; ++ volatile int ktotal = 0; ++ ++ total = 0; ++ for (cnt = 0; cnt < nent; ++cnt) ++ { ++ assert (requests[cnt] == NULL || list[cnt] != NULL); ++ ++ if (requests[cnt] != NULL && list[cnt]->aio_lio_opcode != LIO_NOP) ++ { ++ if (requests[cnt]->kioctx != KCTX_NONE) ++ { ++ assert (requests[cnt]->kioctx == kctx); ++ waitlist[cnt].counterp = &ktotal; ++ ++ktotal; ++ } ++ else ++ { ++ waitlist[cnt].counterp = &total; ++ ++total; ++ } ++#ifndef DONT_NEED_AIO_MISC_COND ++ waitlist[cnt].cond = &cond; ++#endif ++ waitlist[cnt].result = &result; ++ waitlist[cnt].next = requests[cnt]->waiting; ++ waitlist[cnt].sigevp = NULL; ++#ifdef BROKEN_THREAD_SIGNALS ++ waitlist[cnt].caller_pid = 0; /* Not needed. */ ++#endif ++ requests[cnt]->waiting = &waitlist[cnt]; ++ } ++ } ++ ++ while (ktotal > 0) ++ __aio_wait_for_events (kctx, NULL); ++#ifdef DONT_NEED_AIO_MISC_COND ++ AIO_MISC_WAIT (result, total, NULL, 0); ++#else ++ /* Since `pthread_cond_wait'/`pthread_cond_timedwait' are cancellation ++ points we must be careful. We added entries to the waiting lists ++ which we must remove. So defer cancellation for now. */ ++ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldstate); ++ ++ while (total > 0) ++ pthread_cond_wait (&cond, &__aio_requests_mutex); ++ ++ /* Now it's time to restore the cancellation state. */ ++ pthread_setcancelstate (oldstate, NULL); ++ ++ /* Release the conditional variable. */ ++ if (pthread_cond_destroy (&cond) != 0) ++ /* This must never happen. */ ++ abort (); ++#endif ++ ++ if (kctx != KCTX_NONE) ++ { ++ INTERNAL_SYSCALL_DECL (err); ++ INTERNAL_SYSCALL (io_destroy, err, 1, kctx); ++ } ++ ++ /* If any of the I/O requests failed, return -1 and set errno. */ ++ if (result != 0) ++ { ++ __set_errno (result == EINTR ? EINTR : EIO); ++ result = -1; ++ } ++ } ++ else if (sig->sigev_notify != SIGEV_NONE) ++ { ++ struct async_waitlist *waitlist; ++ ++ waitlist = (struct async_waitlist *) ++ malloc (sizeof (struct async_waitlist) ++ + (nent * sizeof (struct waitlist))); ++ ++ if (waitlist == NULL) ++ { ++ __set_errno (EAGAIN); ++ result = -1; ++ } ++ else ++ { ++#ifdef BROKEN_THREAD_SIGNALS ++ pid_t caller_pid = sig->sigev_notify == SIGEV_SIGNAL ? getpid () : 0; ++#endif ++ total = 0; ++ ++ for (cnt = 0; cnt < nent; ++cnt) ++ { ++ assert (requests[cnt] == NULL || list[cnt] != NULL); ++ ++ if (requests[cnt] != NULL ++ && list[cnt]->aio_lio_opcode != LIO_NOP) ++ { ++#ifndef DONT_NEED_AIO_MISC_COND ++ waitlist->list[cnt].cond = NULL; ++#endif ++ waitlist->list[cnt].result = NULL; ++ waitlist->list[cnt].next = requests[cnt]->waiting; ++ waitlist->list[cnt].counterp = &waitlist->counter; ++ waitlist->list[cnt].sigevp = &waitlist->sigev; ++#ifdef BROKEN_THREAD_SIGNALS ++ waitlist->list[cnt].caller_pid = caller_pid; ++#endif ++ requests[cnt]->waiting = &waitlist->list[cnt]; ++ ++total; ++ } ++ } ++ ++ waitlist->counter = total; ++ waitlist->sigev = *sig; ++ } ++ } ++ ++ /* Release the mutex. */ ++ pthread_mutex_unlock (&__aio_requests_mutex); ++ ++ return result; ++} ++ ++ ++#if SHLIB_COMPAT (librt, GLIBC_2_1, GLIBC_2_4) ++int ++attribute_compat_text_section ++__lio_listio_21 (int mode, struct aiocb *const list[], int nent, ++ struct sigevent *sig) ++{ ++ /* Check arguments. */ ++ if (mode != LIO_WAIT && mode != LIO_NOWAIT) ++ { ++ __set_errno (EINVAL); ++ return -1; ++ } ++ ++ return lio_listio_internal (mode | LIO_NO_INDIVIDUAL_EVENT, list, nent, sig); ++} ++compat_symbol (librt, __lio_listio_21, lio_listio, GLIBC_2_1); ++#endif ++ ++ ++int ++__lio_listio_item_notify (int mode, struct aiocb *const list[], int nent, ++ struct sigevent *sig) ++{ ++ /* Check arguments. */ ++ if (mode != LIO_WAIT && mode != LIO_NOWAIT) ++ { ++ __set_errno (EINVAL); ++ return -1; ++ } ++ ++ return lio_listio_internal (mode, list, nent, sig); ++} ++versioned_symbol (librt, __lio_listio_item_notify, lio_listio, GLIBC_2_4); ++ ++#endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/Makefile glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/Makefile +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/Makefile 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/Makefile 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,4 @@ ++ifeq ($(subdir),rtkaio) ++CFLAGS-kaio_mq_send.c += -fexceptions ++CFLAGS-kaio_mq_receive.c += -fexceptions ++endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/powerpc/Makefile glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/powerpc/Makefile +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/powerpc/Makefile 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/powerpc/Makefile 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,3 @@ ++ifeq ($(subdir),rtkaio) ++librtkaio-routines += rtkaio-sysdep ++endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/powerpc/powerpc64/Versions glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/powerpc/powerpc64/Versions +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/powerpc/powerpc64/Versions 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/powerpc/powerpc64/Versions 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,9 @@ ++%ifdef HAVE_FORCED_UNWIND ++librtkaio { ++ GLIBC_2.3.3 { ++ # Changed timer_t. ++ timer_create; timer_delete; timer_getoverrun; timer_gettime; ++ timer_settime; ++ } ++} ++%endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/powerpc/rtkaio-sysdep.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/powerpc/rtkaio-sysdep.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/powerpc/rtkaio-sysdep.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/powerpc/rtkaio-sysdep.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/s390/Makefile glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/s390/Makefile +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/s390/Makefile 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/s390/Makefile 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,3 @@ ++ifeq ($(subdir),rtkaio) ++librtkaio-routines += rtkaio-sysdep ++endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/s390/rtkaio-sysdep.S glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/s390/rtkaio-sysdep.S +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/s390/rtkaio-sysdep.S 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/s390/rtkaio-sysdep.S 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/s390/s390-64/Versions glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/s390/s390-64/Versions +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/s390/s390-64/Versions 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/s390/s390-64/Versions 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,9 @@ ++%ifdef HAVE_FORCED_UNWIND ++librtkaio { ++ GLIBC_2.3.3 { ++ # Changed timer_t. ++ timer_create; timer_delete; timer_getoverrun; timer_gettime; ++ timer_settime; ++ } ++} ++%endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/sparc/kaio_cancel.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/sparc/kaio_cancel.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/sparc/kaio_cancel.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/sparc/kaio_cancel.c 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,33 @@ ++#include ++ ++#define aio_cancel64 XXX ++#include ++#undef aio_cancel64 ++#include ++ ++extern __typeof (aio_cancel) __new_aio_cancel; ++extern __typeof (aio_cancel) __old_aio_cancel; ++ ++#define aio_cancel __new_aio_cancel ++ ++#include ++ ++#undef aio_cancel ++strong_alias (__new_aio_cancel, __new_aio_cancel64); ++versioned_symbol (librt, __new_aio_cancel, aio_cancel, GLIBC_2_3); ++versioned_symbol (librt, __new_aio_cancel64, aio_cancel64, GLIBC_2_3); ++ ++#if SHLIB_COMPAT (librt, GLIBC_2_1, GLIBC_2_3) ++ ++#undef ECANCELED ++#define aio_cancel __old_aio_cancel ++#define ECANCELED 125 ++ ++#include ++ ++#undef aio_cancel ++strong_alias (__old_aio_cancel, __old_aio_cancel64); ++compat_symbol (librt, __old_aio_cancel, aio_cancel, GLIBC_2_1); ++compat_symbol (librt, __old_aio_cancel64, aio_cancel64, GLIBC_2_1); ++ ++#endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/sparc/Makefile glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/sparc/Makefile +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/sparc/Makefile 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/sparc/Makefile 2013-08-16 16:23:23.243028404 +0530 +@@ -0,0 +1,3 @@ ++ifeq ($(subdir),rtkaio) ++librtkaio-routines += rtkaio-sysdep ++endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/sparc/rtkaio-sysdep.c glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/sparc/rtkaio-sysdep.c +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/sparc/rtkaio-sysdep.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/sparc/rtkaio-sysdep.c 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/sparc/sparc64/Versions glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/sparc/sparc64/Versions +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/sparc/sparc64/Versions 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/sparc/sparc64/Versions 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,9 @@ ++%ifdef HAVE_FORCED_UNWIND ++librtkaio { ++ GLIBC_2.3.3 { ++ # Changed timer_t. ++ timer_create; timer_delete; timer_getoverrun; timer_gettime; ++ timer_settime; ++ } ++} ++%endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/sparc/Versions glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/sparc/Versions +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/sparc/Versions 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/sparc/Versions 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,6 @@ ++librtkaio { ++ GLIBC_2.3 { ++ # AIO functions. ++ aio_cancel; aio_cancel64; ++ } ++} +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/syscalls.list glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/syscalls.list +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/syscalls.list 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/syscalls.list 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,5 @@ ++# File name Caller Syscall name Args Strong name Weak names ++ ++kaio_mq_timedsend - mq_timedsend Ci:ipiip __GI_mq_timedsend mq_timedsend ++kaio_mq_timedreceive - mq_timedreceive Ci:ipipp __GI_mq_timedreceive mq_timedreceive ++kaio_mq_setattr - mq_getsetattr i:ipp __GI_mq_setattr mq_setattr +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/x86_64/librtkaio-cancellation.S glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/x86_64/librtkaio-cancellation.S +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/x86_64/librtkaio-cancellation.S 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/x86_64/librtkaio-cancellation.S 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/x86_64/Versions glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/x86_64/Versions +--- glibc-2.17-931-g30bbc0c/rtkaio/sysdeps/unix/sysv/linux/x86_64/Versions 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/sysdeps/unix/sysv/linux/x86_64/Versions 2013-08-16 16:23:23.244028404 +0530 +@@ -0,0 +1,9 @@ ++%ifdef HAVE_FORCED_UNWIND ++librtkaio { ++ GLIBC_2.3.3 { ++ # Changed timer_t. ++ timer_create; timer_delete; timer_getoverrun; timer_gettime; ++ timer_settime; ++ } ++} ++%endif +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aio10.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio10.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aio10.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio10.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aio2.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio2.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aio2.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio2.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aio3.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio3.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aio3.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio3.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aio4.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio4.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aio4.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio4.c 2013-08-16 16:23:23.247028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aio5.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio5.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aio5.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio5.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aio64.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio64.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aio64.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio64.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aio6.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio6.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aio6.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio6.c 2013-08-16 16:23:23.241028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aio7.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio7.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aio7.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio7.c 2013-08-16 16:23:23.241028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aio8.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio8.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aio8.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio8.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aio9.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio9.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aio9.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio9.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aio.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aio.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aio.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod2.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod2.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod2.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod2.c 2013-08-16 16:23:23.241028404 +0530 +@@ -0,0 +1,128 @@ ++/* Test for notification mechanism in lio_listio. ++ Copyright (C) 2000, 2002, 2006 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 2000. ++ ++ 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 ++#include ++#include ++#include ++#include ++#include ++#include "tst-aiod.h" ++ ++ ++static pthread_barrier_t b; ++ ++ ++static void ++thrfct (sigval_t arg) ++{ ++ int e = pthread_barrier_wait (&b); ++ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) ++ { ++ puts ("thread: barrier_wait failed"); ++ exit (1); ++ } ++} ++ ++ ++static int ++do_test (int argc, char *argv[]) ++{ ++ char name[] = "/tmp/aio2.XXXXXX"; ++ int fd; ++ struct aiocb *arr[1]; ++ struct aiocb cb; ++ static const char buf[] = "Hello World\n"; ++ ++ fd = mkstemp (name); ++ if (fd == -1) ++ { ++ printf ("cannot open temp name: %m\n"); ++ return 1; ++ } ++ ++ unlink (name); ++ ++ if (pthread_barrier_init (&b, NULL, 2) != 0) ++ { ++ puts ("barrier_init failed"); ++ return 1; ++ } ++ ++ arr[0] = &cb; ++ ++ void *p; ++ int sz = set_o_direct (fd); ++ if (sz != -1) ++ { ++ int err = posix_memalign (&p, sz, sz); ++ if (err) ++ { ++ errno = err; ++ printf ("cannot allocate memory: %m\n"); ++ return 1; ++ } ++ memcpy (p, buf, sizeof (buf) - 1); ++ memset (p + sizeof (buf) - 1, ' ', sz - sizeof (buf) + 1); ++ printf ("Using O_DIRECT with block size %d\n", sz); ++ } ++ else ++ { ++ p = (void *) buf; ++ sz = sizeof (buf) - 1; ++ } ++ ++ cb.aio_fildes = fd; ++ cb.aio_lio_opcode = LIO_WRITE; ++ cb.aio_reqprio = 0; ++ cb.aio_buf = p; ++ cb.aio_nbytes = sz; ++ cb.aio_offset = 0; ++ cb.aio_sigevent.sigev_notify = SIGEV_THREAD; ++ cb.aio_sigevent.sigev_notify_function = thrfct; ++ cb.aio_sigevent.sigev_notify_attributes = NULL; ++ cb.aio_sigevent.sigev_value.sival_ptr = NULL; ++ ++ if (lio_listio (LIO_WAIT, arr, 1, NULL) < 0) ++ { ++ if (errno == ENOSYS) ++ { ++ puts ("no aio support in this configuration"); ++ return 0; ++ } ++ printf ("lio_listio failed: %m\n"); ++ return 1; ++ } ++ ++ puts ("lio_listio returned"); ++ ++ int e = pthread_barrier_wait (&b); ++ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) ++ { ++ puts ("barrier_wait failed"); ++ return 1; ++ } ++ ++ puts ("all OK"); ++ ++ return 0; ++} ++ ++#include "../test-skeleton.c" +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod3.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod3.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod3.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod3.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1,131 @@ ++/* Test for notification mechanism in lio_listio. ++ Copyright (C) 2000, 2002, 2006 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, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "tst-aiod.h" ++ ++ ++static pthread_barrier_t b; ++ ++ ++static void ++thrfct (sigval_t arg) ++{ ++ int e = pthread_barrier_wait (&b); ++ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) ++ { ++ puts ("child: barrier_wait failed"); ++ exit (1); ++ } ++} ++ ++ ++static int ++do_test (int argc, char *argv[]) ++{ ++ char name[] = "/tmp/aio3.XXXXXX"; ++ int fd; ++ struct aiocb *arr[1]; ++ struct aiocb cb; ++ static const char buf[] = "Hello World\n"; ++ ++ fd = mkstemp (name); ++ if (fd == -1) ++ { ++ printf ("cannot open temp name: %m\n"); ++ return 1; ++ } ++ ++ unlink (name); ++ ++ if (pthread_barrier_init (&b, NULL, 2) != 0) ++ { ++ puts ("barrier_init failed"); ++ return 1; ++ } ++ ++ arr[0] = &cb; ++ ++ void *p; ++ int sz = set_o_direct (fd); ++ if (sz != -1) ++ { ++ int err = posix_memalign (&p, sz, sz); ++ if (err) ++ { ++ errno = err; ++ printf ("cannot allocate memory: %m\n"); ++ return 1; ++ } ++ memcpy (p, buf, sizeof (buf) - 1); ++ memset (p + sizeof (buf) - 1, ' ', sz - sizeof (buf) + 1); ++ printf ("Using O_DIRECT with block size %d\n", sz); ++ } ++ else ++ { ++ p = (void *) buf; ++ sz = sizeof (buf) - 1; ++ } ++ ++ cb.aio_fildes = fd; ++ cb.aio_lio_opcode = LIO_WRITE; ++ cb.aio_reqprio = 0; ++ cb.aio_buf = p; ++ cb.aio_nbytes = sz; ++ cb.aio_offset = 0; ++ cb.aio_sigevent.sigev_notify = SIGEV_THREAD; ++ cb.aio_sigevent.sigev_notify_function = thrfct; ++ cb.aio_sigevent.sigev_notify_attributes = NULL; ++ cb.aio_sigevent.sigev_value.sival_ptr = NULL; ++ ++ if (lio_listio (LIO_NOWAIT, arr, 1, NULL) < 0) ++ { ++ if (errno == ENOSYS) ++ { ++ puts ("no aio support in this configuration"); ++ return 0; ++ } ++ printf ("lio_listio failed: %m\n"); ++ return 1; ++ } ++ ++ if (aio_suspend ((const struct aiocb *const *) arr, 1, NULL) < 0) ++ { ++ printf ("aio_suspend failed: %m\n"); ++ return 1; ++ } ++ ++ int e = pthread_barrier_wait (&b); ++ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) ++ { ++ puts ("parent: barrier_wait failed"); ++ return 1; ++ } ++ ++ puts ("all OK"); ++ ++ return 0; ++} ++ ++#include "../test-skeleton.c" +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod4.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod4.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod4.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod4.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1,182 @@ ++/* Test for completion signal handling. ++ Copyright (C) 2000, 2001, 2002, 2006 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, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "tst-aiod.h" ++ ++/* We might need a bit longer timeout. */ ++#define TIMEOUT 10 /* sec */ ++ ++int my_signo; ++ ++volatile sig_atomic_t flag; ++ ++ ++static void ++sighandler (const int signo) ++{ ++ flag = signo; ++} ++ ++static int ++wait_flag (void) ++{ ++ while (flag == 0) ++ { ++ puts ("Sleeping..."); ++ sleep (1); ++ } ++ ++ if (flag != my_signo) ++ { ++ printf ("signal handler received wrong signal, flag is %d\n", flag); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++#ifndef SIGRTMIN ++# define SIGRTMIN -1 ++# define SIGRTMAX -1 ++#endif ++ ++static int ++do_test (int argc, char *argv[]) ++{ ++ char name[] = "/tmp/aio4.XXXXXX"; ++ int fd; ++ struct aiocb *arr[1]; ++ struct aiocb cb; ++ static const char buf[] = "Hello World\n"; ++ struct aioinit init = {10, 20, 0}; ++ struct sigaction sa; ++ struct sigevent ev; ++ ++ if (SIGRTMIN == -1) ++ { ++ printf ("RT signals not supported.\n"); ++ return 0; ++ } ++ ++ /* Select a signal from the middle of the available choices... */ ++ my_signo = (SIGRTMAX + SIGRTMIN) / 2; ++ ++ fd = mkstemp (name); ++ if (fd == -1) ++ { ++ printf ("cannot open temp name: %m\n"); ++ return 1; ++ } ++ ++ unlink (name); ++ ++ /* Test also aio_init. */ ++ aio_init (&init); ++ ++ arr[0] = &cb; ++ ++ void *p; ++ int sz = set_o_direct (fd); ++ if (sz != -1) ++ { ++ int err = posix_memalign (&p, sz, sz); ++ if (err) ++ { ++ errno = err; ++ printf ("cannot allocate memory: %m\n"); ++ return 1; ++ } ++ memcpy (p, buf, sizeof (buf) - 1); ++ memset (p + sizeof (buf) - 1, ' ', sz - sizeof (buf) + 1); ++ printf ("Using O_DIRECT with block size %d\n", sz); ++ } ++ else ++ { ++ p = (void *) buf; ++ sz = sizeof (buf) - 1; ++ } ++ ++ cb.aio_fildes = fd; ++ cb.aio_lio_opcode = LIO_WRITE; ++ cb.aio_reqprio = 0; ++ cb.aio_buf = p; ++ cb.aio_nbytes = sz; ++ cb.aio_offset = 0; ++ cb.aio_sigevent.sigev_notify = SIGEV_SIGNAL; ++ cb.aio_sigevent.sigev_notify_function = NULL; ++ cb.aio_sigevent.sigev_notify_attributes = NULL; ++ cb.aio_sigevent.sigev_signo = my_signo; ++ cb.aio_sigevent.sigev_value.sival_ptr = NULL; ++ ++ ev.sigev_notify = SIGEV_SIGNAL; ++ ev.sigev_notify_function = NULL; ++ ev.sigev_notify_attributes = NULL; ++ ev.sigev_signo = my_signo; ++ ++ sa.sa_handler = sighandler; ++ sigemptyset (&sa.sa_mask); ++ sa.sa_flags = SA_RESTART; ++ ++ if (sigaction (my_signo, &sa, NULL) < 0) ++ { ++ printf ("sigaction failed: %m\n"); ++ return 1; ++ } ++ ++ flag = 0; ++ /* First use aio_write. */ ++ if (aio_write (arr[0]) < 0) ++ { ++ if (errno == ENOSYS) ++ { ++ puts ("no aio support in this configuration"); ++ return 0; ++ } ++ printf ("aio_write failed: %m\n"); ++ return 1; ++ } ++ ++ if (wait_flag ()) ++ return 1; ++ ++ puts ("aio_write OK"); ++ ++ flag = 0; ++ /* Again with lio_listio. */ ++ if (lio_listio (LIO_NOWAIT, arr, 1, &ev) < 0) ++ { ++ printf ("lio_listio failed: %m\n"); ++ return 1; ++ } ++ ++ if (wait_flag ()) ++ return 1; ++ ++ puts ("all OK"); ++ ++ return 0; ++} ++ ++#include "../test-skeleton.c" +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod5.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod5.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod5.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod5.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1,152 @@ ++/* Test for completion thread handling. ++ Copyright (C) 2000, 2002, 2006 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, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "tst-aiod.h" ++ ++/* We might need a bit longer timeout. */ ++#define TIMEOUT 10 /* sec */ ++ ++#define MY_SIVAL 27 ++ ++volatile sig_atomic_t flag; ++ ++ ++static void ++callback (sigval_t s) ++{ ++ flag = s.sival_int; ++} ++ ++static int ++wait_flag (void) ++{ ++ while (flag == 0) ++ { ++ puts ("Sleeping..."); ++ sleep (1); ++ } ++ ++ if (flag != MY_SIVAL) ++ { ++ printf ("signal handler received wrong signal, flag is %d\n", flag); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++ ++static int ++do_test (int argc, char *argv[]) ++{ ++ char name[] = "/tmp/aio5.XXXXXX"; ++ int fd; ++ struct aiocb *arr[1]; ++ struct aiocb cb; ++ static const char buf[] = "Hello World\n"; ++ struct sigevent ev; ++ ++ fd = mkstemp (name); ++ if (fd == -1) ++ { ++ printf ("cannot open temp name: %m\n"); ++ return 1; ++ } ++ ++ unlink (name); ++ ++ arr[0] = &cb; ++ ++ void *p; ++ int sz = set_o_direct (fd); ++ if (sz != -1) ++ { ++ int err = posix_memalign (&p, sz, sz); ++ if (err) ++ { ++ errno = err; ++ printf ("cannot allocate memory: %m\n"); ++ return 1; ++ } ++ memcpy (p, buf, sizeof (buf) - 1); ++ memset (p + sizeof (buf) - 1, ' ', sz - sizeof (buf) + 1); ++ printf ("Using O_DIRECT with block size %d\n", sz); ++ } ++ else ++ { ++ p = (void *) buf; ++ sz = sizeof (buf) - 1; ++ } ++ ++ cb.aio_fildes = fd; ++ cb.aio_lio_opcode = LIO_WRITE; ++ cb.aio_reqprio = 0; ++ cb.aio_buf = p; ++ cb.aio_nbytes = sz; ++ cb.aio_offset = 0; ++ cb.aio_sigevent.sigev_notify = SIGEV_THREAD; ++ cb.aio_sigevent.sigev_notify_function = callback; ++ cb.aio_sigevent.sigev_notify_attributes = NULL; ++ cb.aio_sigevent.sigev_value.sival_int = MY_SIVAL; ++ ++ ev.sigev_notify = SIGEV_THREAD; ++ ev.sigev_notify_function = callback; ++ ev.sigev_notify_attributes = NULL; ++ ev.sigev_value.sival_int = MY_SIVAL; ++ ++ /* First use aio_write. */ ++ if (aio_write (arr[0]) < 0) ++ { ++ if (errno == ENOSYS) ++ { ++ puts ("no aio support in this configuration"); ++ return 0; ++ } ++ printf ("aio_write failed: %m\n"); ++ return 1; ++ } ++ ++ if (wait_flag ()) ++ return 1; ++ ++ puts ("aio_write OK"); ++ ++ flag = 0; ++ /* Again with lio_listio. */ ++ if (lio_listio (LIO_NOWAIT, arr, 1, &ev) < 0) ++ { ++ printf ("lio_listio failed: %m\n"); ++ return 1; ++ } ++ ++ if (wait_flag ()) ++ return 1; ++ ++ puts ("all OK"); ++ ++ return 0; ++} ++ ++#include "../test-skeleton.c" +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod64.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod64.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod64.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod64.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1,308 @@ ++/* Tests for 64bit AIO in librt. ++ Copyright (C) 1998, 1999, 2000, 2002, 2006 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 1998. ++ ++ 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 _LARGEFILE_SOURCE 1 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "tst-aiod.h" ++ ++ ++/* Prototype for our test function. */ ++extern void do_prepare (int argc, char *argv[]); ++extern int do_test (int argc, char *argv[]); ++ ++/* We have a preparation function. */ ++#define PREPARE do_prepare ++ ++/* We might need a bit longer timeout. */ ++#define TIMEOUT 20 /* sec */ ++ ++/* This defines the `main' function and some more. */ ++#include ++ ++ ++/* These are for the temporary file we generate. */ ++char *name; ++int fd; ++char *tmpbuf; ++int blksz = 100; ++ ++void ++do_prepare (int argc, char *argv[]) ++{ ++ size_t name_len; ++ ++ name_len = strlen (test_dir); ++ name = malloc (name_len + sizeof ("/aioXXXXXX")); ++ mempcpy (mempcpy (name, test_dir, name_len), ++ "/aioXXXXXX", sizeof ("/aioXXXXXX")); ++ add_temp_file (name); ++ ++ /* Open our test file. */ ++ fd = mkstemp (name); ++ if (fd == -1) ++ error (EXIT_FAILURE, errno, "cannot open test file `%s'", name); ++ ++ int sz = set_o_direct (fd); ++ if (sz != -1) ++ { ++ blksz = sz; ++ printf ("Using O_DIRECT with block size %d\n", blksz); ++ } ++} ++ ++ ++static int ++test_file (const void *buf, size_t size, int fd, const char *msg) ++{ ++ struct stat st; ++ char *tmp = tmpbuf; ++ ++ errno = 0; ++ if (fstat (fd, &st) < 0) ++ { ++ error (0, errno, "%s: failed stat", msg); ++ return 1; ++ } ++ ++ if (st.st_size != (off_t) size) ++ { ++ error (0, errno, "%s: wrong size: %lu, should be %lu", ++ msg, (unsigned long int) st.st_size, (unsigned long int) size); ++ return 1; ++ } ++ ++ if (pread (fd, tmp, size, 0) != (ssize_t) size) ++ { ++ error (0, errno, "%s: failed pread", msg); ++ return 1; ++ } ++ ++ if (memcmp (buf, tmp, size) != 0) ++ { ++ error (0, errno, "%s: failed comparison", msg); ++ return 1; ++ } ++ ++ printf ("%s test ok\n", msg); ++ ++ return 0; ++} ++ ++ ++static int ++do_wait (struct aiocb64 **cbp, size_t nent, int allowed_err) ++{ ++ int go_on; ++ size_t cnt; ++ int result = 0; ++ ++ do ++ { ++ aio_suspend64 ((const struct aiocb64 *const *) cbp, nent, NULL); ++ go_on = 0; ++ for (cnt = 0; cnt < nent; ++cnt) ++ if (cbp[cnt] != NULL) ++ { ++ if (aio_error64 (cbp[cnt]) == EINPROGRESS) ++ go_on = 1; ++ else ++ { ++ if (aio_return64 (cbp[cnt]) == -1 ++ && (allowed_err == 0 ++ || aio_error64 (cbp[cnt]) != allowed_err)) ++ { ++ error (0, aio_error64 (cbp[cnt]), "Operation failed\n"); ++ result = 1; ++ } ++ cbp[cnt] = NULL; ++ } ++ } ++ } ++ while (go_on); ++ ++ return result; ++} ++ ++ ++int ++do_test (int argc, char *argv[]) ++{ ++ struct aiocb64 cbs[10]; ++ struct aiocb64 cbs_fsync; ++ struct aiocb64 *cbp[10]; ++ struct aiocb64 *cbp_fsync[1]; ++ char *buf; ++ size_t cnt; ++ int result = 0; ++ ++ buf = mmap (NULL, 20 * blksz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); ++ tmpbuf = buf + 10 * blksz; ++ if (buf == MAP_FAILED) ++ { ++ error (0, errno, "mmap failed"); ++ return 1; ++ } ++ ++ /* Preparation. */ ++ for (cnt = 0; cnt < 10; ++cnt) ++ { ++ cbs[cnt].aio_fildes = fd; ++ cbs[cnt].aio_reqprio = 0; ++ cbs[cnt].aio_buf = memset (&buf[cnt * blksz], '0' + cnt, blksz); ++ cbs[cnt].aio_nbytes = blksz; ++ cbs[cnt].aio_offset = cnt * blksz; ++ cbs[cnt].aio_sigevent.sigev_notify = SIGEV_NONE; ++ ++ cbp[cnt] = &cbs[cnt]; ++ } ++ ++ /* First a simple test. */ ++ for (cnt = 10; cnt > 0; ) ++ if (aio_write64 (cbp[--cnt]) < 0 && errno == ENOSYS) ++ { ++ error (0, 0, "no aio support in this configuration"); ++ return 0; ++ } ++ /* Wait 'til the results are there. */ ++ result |= do_wait (cbp, 10, 0); ++ /* Test this. */ ++ result |= test_file (buf, 10 * blksz, fd, "aio_write"); ++ ++ /* Read now as we've written it. */ ++ memset (buf, '\0', 10 * blksz); ++ /* Issue the commands. */ ++ for (cnt = 10; cnt > 0; ) ++ { ++ --cnt; ++ cbp[cnt] = &cbs[cnt]; ++ aio_read64 (cbp[cnt]); ++ } ++ /* Wait 'til the results are there. */ ++ result |= do_wait (cbp, 10, 0); ++ /* Test this. */ ++ for (cnt = 0; cnt < 10 * blksz; ++cnt) ++ if (buf[cnt] != '0' + (cnt / blksz)) ++ { ++ result = 1; ++ error (0, 0, "comparison failed for aio_read test"); ++ break; ++ } ++ ++ if (cnt == 10 * blksz) ++ puts ("aio_read test ok"); ++ ++ /* Remove the test file contents. */ ++ if (ftruncate64 (fd, 0) < 0) ++ { ++ error (0, errno, "ftruncate failed\n"); ++ result = 1; ++ } ++ ++ /* Test lio_listio. */ ++ for (cnt = 0; cnt < 10; ++cnt) ++ { ++ cbs[cnt].aio_lio_opcode = LIO_WRITE; ++ cbp[cnt] = &cbs[cnt]; ++ } ++ /* Issue the command. */ ++ lio_listio64 (LIO_WAIT, cbp, 10, NULL); ++ /* ...and immediately test it since we started it in wait mode. */ ++ result |= test_file (buf, 10 * blksz, fd, "lio_listio (write)"); ++ ++ /* Test aio_fsync. */ ++ cbs_fsync.aio_fildes = fd; ++ cbs_fsync.aio_sigevent.sigev_notify = SIGEV_NONE; ++ cbp_fsync[0] = &cbs_fsync; ++ ++ /* Remove the test file contents first. */ ++ if (ftruncate64 (fd, 0) < 0) ++ { ++ error (0, errno, "ftruncate failed\n"); ++ result = 1; ++ } ++ ++ /* Write again. */ ++ for (cnt = 10; cnt > 0; ) ++ aio_write64 (cbp[--cnt]); ++ ++ if (aio_fsync64 (O_SYNC, &cbs_fsync) < 0) ++ { ++ error (0, errno, "aio_fsync failed\n"); ++ result = 1; ++ } ++ result |= do_wait (cbp_fsync, 1, 0); ++ ++ /* ...and test since all data should be on disk now. */ ++ result |= test_file (buf, 10 * blksz, fd, "aio_fsync (aio_write)"); ++ ++ /* Test aio_cancel. */ ++ /* Remove the test file contents first. */ ++ if (ftruncate64 (fd, 0) < 0) ++ { ++ error (0, errno, "ftruncate failed\n"); ++ result = 1; ++ } ++ ++ /* Write again. */ ++ for (cnt = 10; cnt > 0; ) ++ aio_write64 (cbp[--cnt]); ++ ++ /* Cancel all requests. */ ++ if (aio_cancel64 (fd, NULL) == -1) ++ printf ("aio_cancel64 (fd, NULL) cannot cancel anything\n"); ++ ++ result |= do_wait (cbp, 10, ECANCELED); ++ ++ /* Another test for aio_cancel. */ ++ /* Remove the test file contents first. */ ++ if (ftruncate64 (fd, 0) < 0) ++ { ++ error (0, errno, "ftruncate failed\n"); ++ result = 1; ++ } ++ ++ /* Write again. */ ++ for (cnt = 10; cnt > 0; ) ++ { ++ --cnt; ++ cbp[cnt] = &cbs[cnt]; ++ aio_write64 (cbp[cnt]); ++ } ++ puts ("finished3"); ++ ++ /* Cancel all requests. */ ++ for (cnt = 10; cnt > 0; ) ++ if (aio_cancel64 (fd, cbp[--cnt]) == -1) ++ /* This is not an error. The request can simply be finished. */ ++ printf ("aio_cancel64 (fd, cbp[%Zd]) cannot be canceled\n", cnt); ++ puts ("finished2"); ++ ++ result |= do_wait (cbp, 10, ECANCELED); ++ ++ puts ("finished"); ++ ++ return result; ++} +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod.c 2013-08-16 16:23:23.247028404 +0530 +@@ -0,0 +1,307 @@ ++/* Tests for AIO in librt. ++ Copyright (C) 1998, 2000, 2002, 2006 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 1998. ++ ++ 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include "tst-aiod.h" ++ ++ ++/* Prototype for our test function. */ ++extern void do_prepare (int argc, char *argv[]); ++extern int do_test (int argc, char *argv[]); ++ ++/* We have a preparation function. */ ++#define PREPARE do_prepare ++ ++/* We might need a bit longer timeout. */ ++#define TIMEOUT 20 /* sec */ ++ ++/* This defines the `main' function and some more. */ ++#include ++ ++ ++/* These are for the temporary file we generate. */ ++char *name; ++int fd; ++char *tmpbuf; ++int blksz = 100; ++ ++void ++do_prepare (int argc, char *argv[]) ++{ ++ size_t name_len; ++ ++ name_len = strlen (test_dir); ++ name = malloc (name_len + sizeof ("/aioXXXXXX")); ++ mempcpy (mempcpy (name, test_dir, name_len), ++ "/aioXXXXXX", sizeof ("/aioXXXXXX")); ++ add_temp_file (name); ++ ++ /* Open our test file. */ ++ fd = mkstemp (name); ++ if (fd == -1) ++ error (EXIT_FAILURE, errno, "cannot open test file `%s'", name); ++ ++ int sz = set_o_direct (fd); ++ if (sz != -1) ++ { ++ blksz = sz; ++ printf ("Using O_DIRECT with block size %d\n", blksz); ++ } ++} ++ ++ ++static int ++test_file (const void *buf, size_t size, int fd, const char *msg) ++{ ++ struct stat st; ++ char *tmp = tmpbuf; ++ ++ errno = 0; ++ if (fstat (fd, &st) < 0) ++ { ++ error (0, errno, "%s: failed stat", msg); ++ return 1; ++ } ++ ++ if (st.st_size != (off_t) size) ++ { ++ error (0, errno, "%s: wrong size: %lu, should be %lu", ++ msg, (unsigned long int) st.st_size, (unsigned long int) size); ++ return 1; ++ } ++ ++ if (pread (fd, tmp, size, 0) != (ssize_t) size) ++ { ++ error (0, errno, "%s: failed pread", msg); ++ return 1; ++ } ++ ++ if (memcmp (buf, tmp, size) != 0) ++ { ++ error (0, errno, "%s: failed comparison", msg); ++ return 1; ++ } ++ ++ printf ("%s test ok\n", msg); ++ ++ return 0; ++} ++ ++ ++static int ++do_wait (struct aiocb **cbp, size_t nent, int allowed_err) ++{ ++ int go_on; ++ size_t cnt; ++ int result = 0; ++ ++ do ++ { ++ aio_suspend ((const struct aiocb *const *) cbp, nent, NULL); ++ go_on = 0; ++ for (cnt = 0; cnt < nent; ++cnt) ++ if (cbp[cnt] != NULL) ++ { ++ if (aio_error (cbp[cnt]) == EINPROGRESS) ++ go_on = 1; ++ else ++ { ++ if (aio_return (cbp[cnt]) == -1 ++ && (allowed_err == 0 ++ || aio_error (cbp[cnt]) != allowed_err)) ++ { ++ error (0, aio_error (cbp[cnt]), "Operation failed\n"); ++ result = 1; ++ } ++ cbp[cnt] = NULL; ++ } ++ } ++ } ++ while (go_on); ++ ++ return result; ++} ++ ++ ++int ++do_test (int argc, char *argv[]) ++{ ++ struct aiocb cbs[10]; ++ struct aiocb cbs_fsync; ++ struct aiocb *cbp[10]; ++ struct aiocb *cbp_fsync[1]; ++ char *buf; ++ size_t cnt; ++ int result = 0; ++ ++ buf = mmap (NULL, 20 * blksz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); ++ tmpbuf = buf + 10 * blksz; ++ if (buf == MAP_FAILED) ++ { ++ error (0, errno, "mmap failed"); ++ return 1; ++ } ++ ++ /* Preparation. */ ++ for (cnt = 0; cnt < 10; ++cnt) ++ { ++ cbs[cnt].aio_fildes = fd; ++ cbs[cnt].aio_reqprio = 0; ++ cbs[cnt].aio_buf = memset (&buf[cnt * blksz], '0' + cnt, blksz); ++ cbs[cnt].aio_nbytes = blksz; ++ cbs[cnt].aio_offset = cnt * blksz; ++ cbs[cnt].aio_sigevent.sigev_notify = SIGEV_NONE; ++ ++ cbp[cnt] = &cbs[cnt]; ++ } ++ ++ /* First a simple test. */ ++ for (cnt = 10; cnt > 0; ) ++ if (aio_write (cbp[--cnt]) < 0 && errno == ENOSYS) ++ { ++ error (0, 0, "no aio support in this configuration"); ++ return 0; ++ } ++ /* Wait 'til the results are there. */ ++ result |= do_wait (cbp, 10, 0); ++ /* Test this. */ ++ result |= test_file (buf, 10 * blksz, fd, "aio_write"); ++ ++ /* Read now as we've written it. */ ++ memset (buf, '\0', 10 * blksz); ++ /* Issue the commands. */ ++ for (cnt = 10; cnt > 0; ) ++ { ++ --cnt; ++ cbp[cnt] = &cbs[cnt]; ++ aio_read (cbp[cnt]); ++ } ++ /* Wait 'til the results are there. */ ++ result |= do_wait (cbp, 10, 0); ++ /* Test this. */ ++ for (cnt = 0; cnt < 10 * blksz; ++cnt) ++ if (buf[cnt] != '0' + (cnt / blksz)) ++ { ++ result = 1; ++ error (0, 0, "comparison failed for aio_read test"); ++ break; ++ } ++ ++ if (cnt == 10 * blksz) ++ puts ("aio_read test ok"); ++ ++ /* Remove the test file contents. */ ++ if (ftruncate (fd, 0) < 0) ++ { ++ error (0, errno, "ftruncate failed\n"); ++ result = 1; ++ } ++ ++ /* Test lio_listio. */ ++ for (cnt = 0; cnt < 10; ++cnt) ++ { ++ cbs[cnt].aio_lio_opcode = LIO_WRITE; ++ cbp[cnt] = &cbs[cnt]; ++ } ++ /* Issue the command. */ ++ lio_listio (LIO_WAIT, cbp, 10, NULL); ++ /* ...and immediately test it since we started it in wait mode. */ ++ result |= test_file (buf, 10 * blksz, fd, "lio_listio (write)"); ++ ++ /* Test aio_fsync. */ ++ cbs_fsync.aio_fildes = fd; ++ cbs_fsync.aio_sigevent.sigev_notify = SIGEV_NONE; ++ cbp_fsync[0] = &cbs_fsync; ++ ++ /* Remove the test file contents first. */ ++ if (ftruncate (fd, 0) < 0) ++ { ++ error (0, errno, "ftruncate failed\n"); ++ result = 1; ++ } ++ ++ /* Write again. */ ++ for (cnt = 10; cnt > 0; ) ++ aio_write (cbp[--cnt]); ++ ++ if (aio_fsync (O_SYNC, &cbs_fsync) < 0) ++ { ++ error (0, errno, "aio_fsync failed\n"); ++ result = 1; ++ } ++ result |= do_wait (cbp_fsync, 1, 0); ++ ++ /* ...and test since all data should be on disk now. */ ++ result |= test_file (buf, 10 * blksz, fd, "aio_fsync (aio_write)"); ++ ++ /* Test aio_cancel. */ ++ /* Remove the test file contents first. */ ++ if (ftruncate (fd, 0) < 0) ++ { ++ error (0, errno, "ftruncate failed\n"); ++ result = 1; ++ } ++ ++ /* Write again. */ ++ for (cnt = 10; cnt > 0; ) ++ aio_write (cbp[--cnt]); ++ ++ /* Cancel all requests. */ ++ if (aio_cancel (fd, NULL) == -1) ++ printf ("aio_cancel (fd, NULL) cannot cancel anything\n"); ++ ++ result |= do_wait (cbp, 10, ECANCELED); ++ ++ /* Another test for aio_cancel. */ ++ /* Remove the test file contents first. */ ++ if (ftruncate (fd, 0) < 0) ++ { ++ error (0, errno, "ftruncate failed\n"); ++ result = 1; ++ } ++ ++ /* Write again. */ ++ for (cnt = 10; cnt > 0; ) ++ { ++ --cnt; ++ cbp[cnt] = &cbs[cnt]; ++ aio_write (cbp[cnt]); ++ } ++ puts ("finished3"); ++ ++ /* Cancel all requests. */ ++ for (cnt = 10; cnt > 0; ) ++ if (aio_cancel (fd, cbp[--cnt]) == -1) ++ /* This is not an error. The request can simply be finished. */ ++ printf ("aio_cancel (fd, cbp[%Zd]) cannot be canceled\n", cnt); ++ puts ("finished2"); ++ ++ result |= do_wait (cbp, 10, ECANCELED); ++ ++ puts ("finished"); ++ ++ return result; ++} +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod.h glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod.h +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-aiod.h 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-aiod.h 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1,53 @@ ++/* Tests for AIO in librt. ++ Copyright (C) 1998, 2000, 2002, 2006 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 1998. ++ ++ 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 ++#include ++#include ++#include ++ ++static int ++set_o_direct (int fd) ++{ ++ int ret = -1; ++#ifdef O_DIRECT ++ if (fcntl (fd, F_SETFL, fcntl (fd, F_GETFL) | O_DIRECT) >= 0) ++ { ++ int pgsz = sysconf (_SC_PAGESIZE); ++ char *buf = mmap (NULL, 16 * pgsz, PROT_READ | PROT_WRITE, ++ MAP_PRIVATE | MAP_ANON, -1, 0); ++ if (buf != MAP_FAILED) ++ { ++ memset (buf, 0, 16 * pgsz); ++ for (int sz = 256; sz <= 16 * pgsz; sz *= 2) ++ if (write (fd, buf, sz) > 0) ++ { ++ ret = sz; ++ break; ++ } ++ ftruncate64 (fd, 0); ++ munmap (buf, 16 * pgsz); ++ } ++ if (ret < 0) ++ fcntl (fd, F_SETFL, fcntl (fd, F_GETFL) & ~O_DIRECT); ++ } ++#endif ++ return ret; ++} +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-clock2.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-clock2.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-clock2.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-clock2.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-clock.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-clock.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-clock.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-clock.c 2013-08-16 16:23:23.247028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-clock_nanosleep.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-clock_nanosleep.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-clock_nanosleep.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-clock_nanosleep.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-cpuclock1.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-cpuclock1.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-cpuclock1.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-cpuclock1.c 2013-08-16 16:23:23.247028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-cpuclock2.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-cpuclock2.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-cpuclock2.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-cpuclock2.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-cputimer1.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-cputimer1.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-cputimer1.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-cputimer1.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-cputimer2.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-cputimer2.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-cputimer2.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-cputimer2.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-cputimer3.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-cputimer3.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-cputimer3.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-cputimer3.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue1.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue1.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue1.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue1.c 2013-08-16 16:23:23.247028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue2.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue2.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue2.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue2.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue3.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue3.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue3.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue3.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue4.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue4.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue4.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue4.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue5.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue5.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue5.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue5.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue6.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue6.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue6.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue6.c 2013-08-16 16:23:23.247028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue7.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue7.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue7.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue7.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue8.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue8.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue8.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue8.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue9.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue9.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue9.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue9.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue.h glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue.h +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-mqueue.h 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-mqueue.h 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-shm.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-shm.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-shm.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-shm.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-timer2.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-timer2.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-timer2.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-timer2.c 2013-08-16 16:23:23.245028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-timer3.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-timer3.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-timer3.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-timer3.c 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-timer4.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-timer4.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-timer4.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-timer4.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-timer5.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-timer5.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-timer5.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-timer5.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/tst-timer.c glibc-2.17-931-g30bbc0c.new/rtkaio/tst-timer.c +--- glibc-2.17-931-g30bbc0c/rtkaio/tst-timer.c 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/tst-timer.c 2013-08-16 16:23:23.246028404 +0530 +@@ -0,0 +1 @@ ++#include +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/Versions glibc-2.17-931-g30bbc0c.new/rtkaio/Versions +--- glibc-2.17-931-g30bbc0c/rtkaio/Versions 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/Versions 2013-08-16 16:23:23.247028404 +0530 +@@ -0,0 +1,25 @@ ++librtkaio { ++ GLIBC_2.1 { ++ # AIO functions. ++ aio_cancel; aio_cancel64; aio_error; aio_error64; aio_fsync; aio_fsync64; ++ aio_init; aio_read; aio_read64; aio_return; aio_return64; aio_suspend; ++ aio_suspend64; aio_write; aio_write64; lio_listio; lio_listio64; ++ } ++ GLIBC_2.2 { ++ # c* ++ clock_getres; clock_gettime; clock_settime; clock_getcpuclockid; ++ clock_nanosleep; ++ ++ # s* ++ shm_open; shm_unlink; ++ ++ # t* ++ timer_create; timer_delete; timer_getoverrun; timer_gettime; ++ timer_settime; ++ } ++ GLIBC_2.3.4 { ++ # m* ++ mq_open; mq_close; mq_unlink; mq_getattr; mq_setattr; ++ mq_notify; mq_send; mq_receive; mq_timedsend; mq_timedreceive; ++ } ++} +diff -pruN glibc-2.17-931-g30bbc0c/rtkaio/Versions.def glibc-2.17-931-g30bbc0c.new/rtkaio/Versions.def +--- glibc-2.17-931-g30bbc0c/rtkaio/Versions.def 1970-01-01 05:30:00.000000000 +0530 ++++ glibc-2.17-931-g30bbc0c.new/rtkaio/Versions.def 2013-08-16 16:23:23.242028404 +0530 +@@ -0,0 +1,8 @@ ++librtkaio { ++ GLIBC_2.1 ++ GLIBC_2.2 ++ GLIBC_2.3 ++ GLIBC_2.3.3 ++ GLIBC_2.3.4 ++ GLIBC_2.4 ++} diff --git a/glibc.spec b/glibc.spec index acd73e6..0fcad01 100644 --- a/glibc.spec +++ b/glibc.spec @@ -1,6 +1,6 @@ %define glibcsrcdir glibc-2.18 %define glibcversion 2.18 -%define glibcrelease 2%{?dist} +%define glibcrelease 3%{?dist} # Pre-release tarballs are pulled in from git using a command that is # effectively: # @@ -88,13 +88,15 @@ Release: %{glibcrelease} License: LGPLv2+ and LGPLv2+ with exceptions and GPLv2+ Group: System Environment/Libraries URL: http://www.gnu.org/software/glibc/ -# TODO: -# The Source1 URL will never reference an upstream URL. In fact the plan -# should be to merge the entire release engineering tarball into upstream -# instead of keeping it around as a large dump of files. Distro specific -# changes should then be a very very small patch set. Source0: %{?glibc_release_url}%{glibcsrcdir}.tar.gz -Source1: %{glibcsrcdir}-releng.tar.gz +Source1: build-locale-archive.c +Source2: glibc_post_upgrade.c +Source3: libc-lock.h +Source4: nscd.conf +Source5: nscd.service +Source6: nscd.socket +Source7: nsswitch.conf +Source8: power6emul.c ############################################################################## # Start of glibc patches @@ -168,6 +170,11 @@ Patch0034: %{name}-fedora-elf-init-hidden_undef.patch Patch0035: %{name}-rh911307.patch Patch0037: %{name}-rh952799.patch +# rtkaio and c_stubs. Note that despite the numbering, these are always +# applied first. +Patch0038: %{name}-rtkaio.patch +Patch0039: %{name}-c_stubs.patch + # # Patches from upstream # @@ -476,10 +483,13 @@ package or when debugging this package. # Prepare for the build. ############################################################################## %prep -%setup -q -n %{glibcsrcdir} -b1 +%setup -q -n %{glibcsrcdir} # Patch order is important as some patches depend on other patches and -# therefore the order must not be changed. +# therefore the order must not be changed. First two are rtkaio and c_stubs; +# we maintain this only in Fedora. +%patch0038 -p1 +%patch0039 -p1 %patch0001 -p1 %patch0003 -p1 %patch0004 -p1 @@ -693,7 +703,7 @@ build nosegneg -mno-tls-direct-seg-refs platform=`LD_SHOW_AUXV=1 /bin/true | sed -n 's/^AT_PLATFORM:[[:blank:]]*//p'` if [ "$platform" != power6 ]; then mkdir -p power6emul/{lib,lib64} - $GCC -shared -O2 -fpic -o power6emul/%{_lib}/power6emul.so releng/power6emul.c -Wl,-z,initfirst + $GCC -shared -O2 -fpic -o power6emul/%{_lib}/power6emul.so %{SOURCE8} -Wl,-z,initfirst %ifarch ppc gcc -shared -nostdlib -O2 -fpic -m64 -o power6emul/lib64/power6emul.so -xc - needs sanitizing as well. -cp -a releng/libc-lock.h $RPM_BUILD_ROOT%{_prefix}/include/bits/libc-lock.h +cp -a %{SOURCE3} $RPM_BUILD_ROOT%{_prefix}/include/bits/libc-lock.h # XXX: What is this for? ln -sf libbsd-compat.a $RPM_BUILD_ROOT%{_libdir}/libbsd.a @@ -1158,19 +1168,24 @@ EOF # Won't this impact what is shipped? rm -rf $RPM_BUILD_ROOT%{_prefix}/share/zoneinfo -# Make sure %config files have the same timestamp -touch -r releng/glibc.spec.in $RPM_BUILD_ROOT/etc/ld.so.conf +# Make sure %config files have the same timestamp across multilib packages. +# +# XXX: Ideally ld.so.conf should have the timestamp of the spec file, but there +# doesn't seem to be any macro to give us that. So we do the next best thing, +# which is to at least keep the timestamp consistent. The choice of using +# glibc_post_upgrade.c is arbitrary. +touch -r %{SOURCE2} $RPM_BUILD_ROOT/etc/ld.so.conf touch -r sunrpc/etc.rpc $RPM_BUILD_ROOT/etc/rpc # We allow undefined symbols in shared libraries because the libraries # referenced at link time here, particularly ld.so, may be different than # the one used at runtime. This is really only needed during the ARM # transition from ld-linux.so.3 to ld-linux-armhf.so.3. -pushd releng -$GCC -Os -g -o build-locale-archive build-locale-archive.c \ +pushd build-%{target} +$GCC -Os -g -o build-locale-archive %{SOURCE1} \ ../build-%{target}/locale/locarchive.o \ ../build-%{target}/locale/md5.o \ - -DDATADIR=\"%{_datadir}\" -DPREFIX=\"%{_prefix}\" \ + -I. -DDATADIR=\"%{_datadir}\" -DPREFIX=\"%{_prefix}\" \ -L../build-%{target} \ -Wl,--allow-shlib-undefined \ -B../build-%{target}/csu/ -lc -lc_nonshared diff --git a/glibc_post_upgrade.c b/glibc_post_upgrade.c new file mode 100644 index 0000000..85309bf --- /dev/null +++ b/glibc_post_upgrade.c @@ -0,0 +1,340 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define verbose_exec(failcode, path...) \ + do \ + { \ + char *const arr[] = { path, NULL }; \ + vexec (failcode, arr); \ + } while (0) + +__attribute__((noinline)) void vexec (int failcode, char *const path[]); +__attribute__((noinline)) void says (const char *str); +__attribute__((noinline)) void sayn (long num); +__attribute__((noinline)) void message (char *const path[]); +__attribute__((noinline)) int check_elf (const char *name); + +#ifdef __i386__ +static int +is_ia64 (void) +{ + unsigned int fl1, fl2; + + /* See if we can use cpuid. */ + __asm__ ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;" + "pushl %0; popfl; pushfl; popl %0; popfl" + : "=&r" (fl1), "=&r" (fl2) + : "i" (0x00200000)); + if (((fl1 ^ fl2) & 0x00200000) == 0) + return 0; + + /* Host supports cpuid. See if cpuid gives capabilities, try + CPUID(0). Preserve %ebx and %ecx; cpuid insn clobbers these, we + don't need their CPUID values here, and %ebx may be the PIC + register. */ + __asm__ ("pushl %%ecx; pushl %%ebx; cpuid; popl %%ebx; popl %%ecx" + : "=a" (fl1) : "0" (0) : "edx", "cc"); + if (fl1 == 0) + return 0; + + /* Invoke CPUID(1), return %edx; caller can examine bits to + determine what's supported. */ + __asm__ ("pushl %%ecx; pushl %%ebx; cpuid; popl %%ebx; popl %%ecx" + : "=d" (fl2), "=a" (fl1) : "1" (1) : "cc"); + return (fl2 & (1 << 30)) != 0; +} +#else +#define is_ia64() 0 +#endif + +int +main (void) +{ + struct stat statbuf; + char initpath[256]; + + char buffer[4096]; + struct pref { + char *p; + int len; + } prefix[] = { { "libc-", 5 }, { "libm-", 5 }, + { "librt-", 6 }, { "libpthread-", 11 }, + { "librtkaio-", 10 }, { "libthread_db-", 13 } }; + int i, j, fd; + off_t base; + ssize_t ret; +#ifdef __i386__ + const char *remove_dirs[] = { "/lib/tls", "/lib/i686", "/lib/tls/i486", "/lib/tls/i586", "/lib/tls/i686" }; +#else +#ifndef LIBTLS +#define LIBTLS "/lib/tls" +#endif + const char *remove_dirs[] = { LIBTLS }; +#endif + for (j = 0; j < sizeof (remove_dirs) / sizeof (remove_dirs[0]); ++j) + { + size_t rmlen = strlen (remove_dirs[j]); + fd = open (remove_dirs[j], O_RDONLY); + if (fd >= 0 + && (ret = getdirentries (fd, buffer, sizeof (buffer), &base)) + >= (ssize_t) offsetof (struct dirent, d_name)) + { + for (base = 0; base + offsetof (struct dirent, d_name) < ret; ) + { + struct dirent *d = (struct dirent *) (buffer + base); + + for (i = 0; i < sizeof (prefix) / sizeof (prefix[0]); i++) + if (! strncmp (d->d_name, prefix[i].p, prefix[i].len)) + { + char *p = d->d_name + prefix[i].len; + + while (*p == '.' || (*p >= '0' && *p <= '9')) p++; + if (p[0] == 's' && p[1] == 'o' && p[2] == '\0' + && p + 3 - d->d_name + < sizeof (initpath) - rmlen - 1) + { + memcpy (initpath, remove_dirs[j], rmlen); + initpath[rmlen] = '/'; + strcpy (initpath + rmlen + 1, d->d_name); + unlink (initpath); + break; + } + } + base += d->d_reclen; + } + close (fd); + } + } + + int ldsocfd = open (LD_SO_CONF, O_RDONLY); + struct stat ldsocst; + if (ldsocfd >= 0 && fstat (ldsocfd, &ldsocst) >= 0) + { + char p[ldsocst.st_size + 1]; + if (read (ldsocfd, p, ldsocst.st_size) == ldsocst.st_size) + { + p[ldsocst.st_size] = '\0'; + if (strstr (p, "include ld.so.conf.d/*.conf") == NULL) + { + close (ldsocfd); + ldsocfd = open (LD_SO_CONF, O_WRONLY | O_TRUNC); + if (ldsocfd >= 0) + { + size_t slen = strlen ("include ld.so.conf.d/*.conf\n"); + if (write (ldsocfd, "include ld.so.conf.d/*.conf\n", slen) + != slen + || write (ldsocfd, p, ldsocst.st_size) != ldsocst.st_size) + _exit (109); + } + } + } + if (ldsocfd >= 0) + close (ldsocfd); + } + + /* If installing bi-arch glibc, rpm sometimes doesn't unpack all files + before running one of the lib's %post scriptlet. /sbin/ldconfig will + then be run by the other arch's %post. */ + if (! access ("/sbin/ldconfig", X_OK)) + verbose_exec (110, "/sbin/ldconfig", "/sbin/ldconfig"); + + if (! utimes (GCONV_MODULES_DIR "/gconv-modules.cache", NULL)) + { +#ifndef ICONVCONFIG +#define ICONVCONFIG "/usr/sbin/iconvconfig" +#endif + const char *iconv_cache = GCONV_MODULES_DIR"/gconv-modules.cache"; + const char *iconv_dir = GCONV_MODULES_DIR; + if (is_ia64 ()) + { + iconv_cache = "/emul/ia32-linux"GCONV_MODULES_DIR"/gconv-modules.cache"; + iconv_dir = "/emul/ia32-linux"GCONV_MODULES_DIR; + } + verbose_exec (113, ICONVCONFIG, "/usr/sbin/iconvconfig", + "-o", iconv_cache, + "--nostdlib", iconv_dir); + } + + /* Check if telinit is available and either SysVInit fifo, + or upstart telinit. */ + if (access ("/sbin/telinit", X_OK) + || ((!!access ("/dev/initctl", F_OK)) + ^ !access ("/sbin/initctl", X_OK))) + _exit (0); + + /* Check if we are not inside of some chroot, because we'd just + timeout and leave /etc/initrunlvl. + + On more modern systems this test is not sufficient to detect + if we're in a chroot. */ + if (readlink ("/proc/1/exe", initpath, 256) <= 0 || + readlink ("/proc/1/root", initpath, 256) <= 0) + _exit (0); + + /* Here's another well known way to detect chroot, at least on an + ext and xfs filesystems and assuming nothing mounted on the chroot's + root. */ + if (stat ("/", &statbuf) != 0 + || (statbuf.st_ino != 2 + && statbuf.st_ino != 128)) + _exit (0); + + if (check_elf ("/proc/1/exe")) + verbose_exec (116, "/sbin/telinit", "/sbin/telinit", "u"); + + /* Check if we can safely condrestart sshd. */ + if (access ("/sbin/service", X_OK) == 0 + && access ("/usr/sbin/sshd", X_OK) == 0 + && access ("/etc/rc.d/init.d/sshd", X_OK) == 0 + && access ("/bin/bash", X_OK) == 0) + { + if (check_elf ("/usr/sbin/sshd")) + verbose_exec (-121, "/sbin/service", "/sbin/service", "sshd", "condrestart"); + } + + _exit(0); +} + +void +vexec (int failcode, char *const path[]) +{ + pid_t pid; + int status, save_errno; + int devnull = 0; + + if (failcode < 0) + { + devnull = 1; + failcode = -failcode; + } + pid = vfork (); + if (pid == 0) + { + int fd; + if (devnull && (fd = open ("/dev/null", O_WRONLY)) >= 0) + { + dup2 (fd, 1); + dup2 (fd, 2); + close (fd); + } + execv (path[0], path + 1); + save_errno = errno; + message (path); + says (" exec failed with errno "); + sayn (save_errno); + says ("\n"); + _exit (failcode); + } + else if (pid < 0) + { + save_errno = errno; + message (path); + says (" fork failed with errno "); + sayn (save_errno); + says ("\n"); + _exit (failcode + 1); + } + if (waitpid (0, &status, 0) != pid || !WIFEXITED (status)) + { + message (path); + says (" child terminated abnormally\n"); + _exit (failcode + 2); + } + if (WEXITSTATUS (status)) + { + message (path); + says (" child exited with exit code "); + sayn (WEXITSTATUS (status)); + says ("\n"); + _exit (WEXITSTATUS (status)); + } +} + +void +says (const char *str) +{ + write (1, str, strlen (str)); +} + +void +sayn (long num) +{ + char string[sizeof (long) * 3 + 1]; + char *p = string + sizeof (string) - 1; + + *p = '\0'; + if (num == 0) + *--p = '0'; + else + while (num) + { + *--p = '0' + num % 10; + num = num / 10; + } + + says (p); +} + +void +message (char *const path[]) +{ + says ("/usr/sbin/glibc_post_upgrade: While trying to execute "); + says (path[0]); +} + +int +check_elf (const char *name) +{ + /* Play safe, if we can't open or read, assume it might be + ELF for the current arch. */ + int ret = 1; + int fd = open (name, O_RDONLY); + if (fd >= 0) + { + Elf32_Ehdr ehdr; + if (read (fd, &ehdr, offsetof (Elf32_Ehdr, e_version)) + == offsetof (Elf32_Ehdr, e_version)) + { + ret = 0; + if (ehdr.e_ident[EI_CLASS] + == (sizeof (long) == 8 ? ELFCLASS64 : ELFCLASS32)) + { +#if defined __i386__ + ret = ehdr.e_machine == EM_386; +#elif defined __x86_64__ + ret = ehdr.e_machine == EM_X86_64; +#elif defined __ia64__ + ret = ehdr.e_machine == EM_IA_64; +#elif defined __powerpc64__ + ret = ehdr.e_machine == EM_PPC64; +#elif defined __powerpc__ + ret = ehdr.e_machine == EM_PPC; +#elif defined __s390__ || defined __s390x__ + ret = ehdr.e_machine == EM_S390; +#elif defined __x86_64__ + ret = ehdr.e_machine == EM_X86_64; +#elif defined __sparc__ + if (sizeof (long) == 8) + ret = ehdr.e_machine == EM_SPARCV9; + else + ret = (ehdr.e_machine == EM_SPARC + || ehdr.e_machine == EM_SPARC32PLUS); +#else + ret = 1; +#endif + } + } + close (fd); + } + return ret; +} diff --git a/libc-lock.h b/libc-lock.h new file mode 100644 index 0000000..d243ef0 --- /dev/null +++ b/libc-lock.h @@ -0,0 +1,340 @@ +/* libc-internal interface for mutex locks. LinuxThreads version. + Copyright (C) 1996,1997,1998,1999,2000,2001,2002,2003 + 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; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_LIBC_LOCK_H +#define _BITS_LIBC_LOCK_H 1 + +#include + +/* Mutex type. */ +#ifdef _IO_MTSAFE_IO +typedef pthread_mutex_t __libc_lock_t; +typedef struct { pthread_mutex_t mutex; } __libc_lock_recursive_t; +# ifdef __USE_UNIX98 +typedef pthread_rwlock_t __libc_rwlock_t; +# else +typedef struct __libc_rwlock_opaque__ __libc_rwlock_t; +# endif +typedef __libc_lock_recursive_t __rtld_lock_recursive_t; +#else +typedef struct __libc_lock_opaque__ __libc_lock_t; +typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; +typedef struct __libc_rwlock_opaque__ __libc_rwlock_t; +#endif + +/* Type for key to thread-specific data. */ +typedef pthread_key_t __libc_key_t; + +/* Define a lock variable NAME with storage class CLASS. The lock must be + initialized with __libc_lock_init before it can be used (or define it + with __libc_lock_define_initialized, below). Use `extern' for CLASS to + declare a lock defined in another module. In public structure + definitions you must use a pointer to the lock structure (i.e., NAME + begins with a `*'), because its storage size will not be known outside + of libc. */ +#define __libc_lock_define(CLASS,NAME) \ + CLASS __libc_lock_t NAME; +#define __libc_rwlock_define(CLASS,NAME) \ + CLASS __libc_rwlock_t NAME; +#define __libc_lock_define_recursive(CLASS,NAME) \ + CLASS __libc_lock_recursive_t NAME; +#define __rtld_lock_define_recursive(CLASS,NAME) \ + CLASS __rtld_lock_recursive_t NAME; + +/* Define an initialized lock variable NAME with storage class CLASS. + + For the C library we take a deeper look at the initializer. For + this implementation all fields are initialized to zero. Therefore + we don't initialize the variable which allows putting it into the + BSS section. (Except on PA-RISC and other odd architectures, where + initialized locks must be set to one due to the lack of normal + atomic operations.) */ + +#if __LT_SPINLOCK_INIT == 0 +# define __libc_lock_define_initialized(CLASS,NAME) \ + CLASS __libc_lock_t NAME; +#else +# define __libc_lock_define_initialized(CLASS,NAME) \ + CLASS __libc_lock_t NAME = PTHREAD_MUTEX_INITIALIZER; +#endif + +#define __libc_rwlock_define_initialized(CLASS,NAME) \ + CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER; + +/* Define an initialized recursive lock variable NAME with storage + class CLASS. */ +#define __libc_lock_define_initialized_recursive(CLASS,NAME) \ + CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER; +#define _LIBC_LOCK_RECURSIVE_INITIALIZER \ + {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} + +#define __rtld_lock_define_initialized_recursive(CLASS,NAME) \ + CLASS __rtld_lock_recursive_t NAME = _RTLD_LOCK_RECURSIVE_INITIALIZER; +#define _RTLD_LOCK_RECURSIVE_INITIALIZER \ + {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} + +#if defined __PIC__ +# define __libc_maybe_call(FUNC, ARGS, ELSE) \ + (__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \ + _fn != NULL ? (*_fn) ARGS : ELSE; })) +#else +# define __libc_maybe_call(FUNC, ARGS, ELSE) \ + (FUNC != NULL ? FUNC ARGS : ELSE) +#endif +#define __libc_maybe_call2(FUNC, ARGS, ELSE) __libc_maybe_call (__##FUNC, ARGS, ELSE) + +/* Initialize the named lock variable, leaving it in a consistent, unlocked + state. */ +#define __libc_lock_init(NAME) \ + (__libc_maybe_call2 (pthread_mutex_init, (&(NAME), NULL), 0)) +#define __libc_rwlock_init(NAME) \ + (__libc_maybe_call (__pthread_rwlock_init, (&(NAME), NULL), 0)); + +/* Same as last but this time we initialize a recursive mutex. */ +#define __libc_lock_init_recursive(NAME) \ + do { \ + if (__pthread_mutex_init != NULL) \ + { \ + pthread_mutexattr_t __attr; \ + __pthread_mutexattr_init (&__attr); \ + __pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP); \ + __pthread_mutex_init (&(NAME).mutex, &__attr); \ + __pthread_mutexattr_destroy (&__attr); \ + } \ + } while (0); +#define __rtld_lock_init_recursive(NAME) \ + __libc_lock_init_recursive (NAME) + +/* Finalize the named lock variable, which must be locked. It cannot be + used again until __libc_lock_init is called again on it. This must be + called on a lock variable before the containing storage is reused. */ +#define __libc_lock_fini(NAME) \ + (__libc_maybe_call2 (pthread_mutex_destroy, (&(NAME)), 0)); +#define __libc_rwlock_fini(NAME) \ + (__libc_maybe_call (__pthread_rwlock_destroy, (&(NAME)), 0)); + +/* Finalize recursive named lock. */ +#define __libc_lock_fini_recursive(NAME) __libc_lock_fini ((NAME).mutex) +#define __rtld_lock_fini_recursive(NAME) __libc_lock_fini_recursive (NAME) + +/* Lock the named lock variable. */ +#define __libc_lock_lock(NAME) \ + (__libc_maybe_call2 (pthread_mutex_lock, (&(NAME)), 0)); +#define __libc_rwlock_rdlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_rdlock, (&(NAME)), 0)); +#define __libc_rwlock_wrlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_wrlock, (&(NAME)), 0)); + +/* Lock the recursive named lock variable. */ +#define __libc_lock_lock_recursive(NAME) __libc_lock_lock ((NAME).mutex) + +/* Try to lock the named lock variable. */ +#define __libc_lock_trylock(NAME) \ + (__libc_maybe_call2 (pthread_mutex_trylock, (&(NAME)), 0)) +#define __libc_rwlock_tryrdlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_tryrdlock, (&(NAME)), 0)) +#define __libc_rwlock_trywrlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_trywrlock, (&(NAME)), 0)) + +/* Try to lock the recursive named lock variable. */ +#define __libc_lock_trylock_recursive(NAME) __libc_lock_trylock ((NAME).mutex) +#define __rtld_lock_trylock_recursive(NAME) \ + __libc_lock_trylock_recursive (NAME) + +/* Unlock the named lock variable. */ +#define __libc_lock_unlock(NAME) \ + (__libc_maybe_call2 (pthread_mutex_unlock, (&(NAME)), 0)); +#define __libc_rwlock_unlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_unlock, (&(NAME)), 0)); + +/* Unlock the recursive named lock variable. */ +#define __libc_lock_unlock_recursive(NAME) __libc_lock_unlock ((NAME).mutex) + +#define __rtld_lock_lock_recursive(NAME) __libc_lock_lock_recursive (NAME) +#define __rtld_lock_unlock_recursive(NAME) __libc_lock_unlock_recursive (NAME) + +/* Define once control variable. */ +#if PTHREAD_ONCE_INIT == 0 +/* Special case for static variables where we can avoid the initialization + if it is zero. */ +# define __libc_once_define(CLASS, NAME) \ + CLASS pthread_once_t NAME +#else +# define __libc_once_define(CLASS, NAME) \ + CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT +#endif + +/* Call handler iff the first call. */ +#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \ + do { \ + if (__pthread_once != NULL) \ + __pthread_once (&(ONCE_CONTROL), (INIT_FUNCTION)); \ + else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) { \ + INIT_FUNCTION (); \ + (ONCE_CONTROL) = 2; \ + } \ + } while (0) + + +/* Start critical region with cleanup. */ +#define __libc_cleanup_region_start(DOIT, FCT, ARG) \ + { struct _pthread_cleanup_buffer _buffer; \ + int _avail = (DOIT) && _pthread_cleanup_push_defer != NULL; \ + if (_avail) { \ + _pthread_cleanup_push_defer (&_buffer, (FCT), (ARG)); \ + } + +/* End critical region with cleanup. */ +#define __libc_cleanup_region_end(DOIT) \ + if (_avail) { \ + _pthread_cleanup_pop_restore (&_buffer, (DOIT)); \ + } \ + } + +/* Sometimes we have to exit the block in the middle. */ +#define __libc_cleanup_end(DOIT) \ + if (_avail) { \ + _pthread_cleanup_pop_restore (&_buffer, (DOIT)); \ + } + +#define __libc_cleanup_push(fct, arg) \ + { struct _pthread_cleanup_buffer _buffer; \ + __libc_maybe_call (_pthread_cleanup_push, (&_buffer, (fct), (arg)), 0) + +#define __libc_cleanup_pop(execute) \ + __libc_maybe_call (_pthread_cleanup_pop, (&_buffer, execute), 0); \ + } + +/* Create thread-specific key. */ +#define __libc_key_create(KEY, DESTRUCTOR) \ + (__libc_maybe_call (__pthread_key_create, (KEY, DESTRUCTOR), 1)) + +/* Get thread-specific data. */ +#define __libc_getspecific(KEY) \ + (__libc_maybe_call (__pthread_getspecific, (KEY), NULL)) + +/* Set thread-specific data. */ +#define __libc_setspecific(KEY, VALUE) \ + (__libc_maybe_call (__pthread_setspecific, (KEY, VALUE), 0)) + + +/* Register handlers to execute before and after `fork'. */ +#define __libc_atfork(PREPARE, PARENT, CHILD) \ + (__libc_maybe_call (__pthread_atfork, (PREPARE, PARENT, CHILD), 0)) + +__BEGIN_DECLS + +extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer, + void (*__routine) (void *), + void *__arg) __THROW; + +extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer, + int __execute) __THROW; + + +/* Functions that are used by this file and are internal to the GNU C + library. */ + +extern int __pthread_mutex_init (pthread_mutex_t *__mutex, + __const pthread_mutexattr_t *__mutex_attr); + +extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_lock (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex); + +extern int __pthread_mutexattr_init (pthread_mutexattr_t *__attr); + +extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr); + +extern int __pthread_mutexattr_settype (pthread_mutexattr_t *__attr, + int __kind); + +#ifdef __USE_UNIX98 +extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock, + __const pthread_rwlockattr_t *__attr); + +extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock); +#endif + +extern int __pthread_key_create (pthread_key_t *__key, + void (*__destr_function) (void *)); + +extern int __pthread_setspecific (pthread_key_t __key, + __const void *__pointer); + +extern void *__pthread_getspecific (pthread_key_t __key); + +extern int __pthread_once (pthread_once_t *__once_control, + void (*__init_routine) (void)); + +extern int __pthread_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void)); + +__END_DECLS + +/* Make the pthread functions weak so that we can elide them from + single-threaded processes. */ +#ifndef __NO_WEAK_PTHREAD_ALIASES +# pragma weak __pthread_mutex_init +# pragma weak __pthread_mutex_destroy +# pragma weak __pthread_mutex_lock +# pragma weak __pthread_mutex_trylock +# pragma weak __pthread_mutex_unlock +# pragma weak __pthread_mutexattr_init +# pragma weak __pthread_mutexattr_destroy +# pragma weak __pthread_mutexattr_settype +# pragma weak __pthread_rwlock_destroy +# pragma weak __pthread_rwlock_rdlock +# pragma weak __pthread_rwlock_tryrdlock +# pragma weak __pthread_rwlock_wrlock +# pragma weak __pthread_rwlock_trywrlock +# pragma weak __pthread_rwlock_unlock +# pragma weak __pthread_key_create +# pragma weak __pthread_setspecific +# pragma weak __pthread_getspecific +# pragma weak __pthread_once +# pragma weak __pthread_initialize +# pragma weak __pthread_atfork +# pragma weak _pthread_cleanup_push_defer +# pragma weak _pthread_cleanup_pop_restore +# pragma weak _pthread_cleanup_push +# pragma weak _pthread_cleanup_pop +#endif + +/* We need portable names for some functions. E.g., when they are + used as argument to __libc_cleanup_region_start. */ +#define __libc_mutex_unlock __pthread_mutex_unlock + +#endif /* bits/libc-lock.h */ diff --git a/nscd.conf b/nscd.conf new file mode 100644 index 0000000..8a24a78 --- /dev/null +++ b/nscd.conf @@ -0,0 +1 @@ +d /run/nscd 0755 root root diff --git a/nscd.service b/nscd.service new file mode 100644 index 0000000..744a5c8 --- /dev/null +++ b/nscd.service @@ -0,0 +1,18 @@ +[Unit] +Description=Name Service Cache Daemon +After=syslog.target + +[Service] +EnvironmentFile=-/etc/sysconfig/nscd +ExecStart=/usr/sbin/nscd --foreground $NSCD_OPTIONS +ExecStop=/usr/sbin/nscd --shutdown +ExecReload=/usr/sbin/nscd -i passwd +ExecReload=/usr/sbin/nscd -i group +ExecReload=/usr/sbin/nscd -i hosts +ExecReload=/usr/sbin/nscd -i services +ExecReload=/usr/sbin/nscd -i netgroup +Restart=always + +[Install] +WantedBy=multi-user.target +Also=nscd.socket diff --git a/nscd.socket b/nscd.socket new file mode 100644 index 0000000..7e512d5 --- /dev/null +++ b/nscd.socket @@ -0,0 +1,8 @@ +[Unit] +Description=Name Service Cache Daemon Socket + +[Socket] +ListenDatagram=/var/run/nscd/socket + +[Install] +WantedBy=sockets.target diff --git a/nsswitch.conf b/nsswitch.conf new file mode 100644 index 0000000..2f6c84e --- /dev/null +++ b/nsswitch.conf @@ -0,0 +1,63 @@ +# +# /etc/nsswitch.conf +# +# An example Name Service Switch config file. This file should be +# sorted with the most-used services at the beginning. +# +# The entry '[NOTFOUND=return]' means that the search for an +# entry should stop if the search in the previous entry turned +# up nothing. Note that if the search failed due to some other reason +# (like no NIS server responding) then the search continues with the +# next entry. +# +# Valid entries include: +# +# nisplus Use NIS+ (NIS version 3) +# nis Use NIS (NIS version 2), also called YP +# dns Use DNS (Domain Name Service) +# files Use the local files +# db Use the local database (.db) files +# compat Use NIS on compat mode +# hesiod Use Hesiod for user lookups +# [NOTFOUND=return] Stop searching if not found so far +# + +# To use db, put the "db" in front of "files" for entries you want to be +# looked up first in the databases +# +# Example: +#passwd: db files nisplus nis +#shadow: db files nisplus nis +#group: db files nisplus nis + +passwd: files sss +shadow: files sss +group: files sss +initgroups: files + +#hosts: db files nisplus nis dns +hosts: files dns + +# Example - obey only what nisplus tells us... +#services: nisplus [NOTFOUND=return] files +#networks: nisplus [NOTFOUND=return] files +#protocols: nisplus [NOTFOUND=return] files +#rpc: nisplus [NOTFOUND=return] files +#ethers: nisplus [NOTFOUND=return] files +#netmasks: nisplus [NOTFOUND=return] files + +bootparams: nisplus [NOTFOUND=return] files + +ethers: files +netmasks: files +networks: files +protocols: files +rpc: files +services: files sss + +netgroup: nisplus sss + +publickey: nisplus + +automount: files nisplus +aliases: files nisplus diff --git a/power6emul.c b/power6emul.c new file mode 100644 index 0000000..1b0187b --- /dev/null +++ b/power6emul.c @@ -0,0 +1,273 @@ +/* Emulate power6 mf[tf]gpr and fri[zpmn] instructions. + Copyright (C) 2006 Red Hat, Inc. + Contributed by Jakub Jelinek , 2006. + + This 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. + + It 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 +#include + +extern double frip (double), friz (double), frin (double), frim (double); +asm (".globl frip, friz, frin, frim\n.hidden frip, friz, frin, frim\n\t" +#ifdef __powerpc64__ + ".section \".toc\",\"aw\"\n" +"8:" ".tc FD_43300000_0[TC],0x4330000000000000\n" +"9:" ".tc FD_3fe00000_0[TC],0x3fe0000000000000\n\t" + ".previous\n\t" +#else + ".rodata\n\t" + ".align 2\n" +"8:" ".long 0x59800000\n" +"9:" ".long 0x3f000000\n\t" + ".previous\n\t" +#endif + "# frip == ceil\n" +"frip:" "mffs 11\n\t" +#ifdef __powerpc64__ + "lfd 13,8b@toc(2)\n\t" +#else + "mflr 11\n\t" + "bcl 20,31,1f\n" +"1:" "mflr 9\n\t" + "addis 9,9,8b-1b@ha\n\t" + "lfs 13,8b-1b@l(9)\n\t" + "mtlr 11\n\t" +#endif + "fabs 0,1\n\t" + "fsub 12,13,13\n\t" + "fcmpu 7,0,13\n\t" + "fcmpu 6,1,12\n\t" + "bnllr- 7\n\t" + "mtfsfi 7,2\n\t" + "ble- 6,2f\n\t" + "fadd 1,1,13\n\t" + "fsub 1,1,13\n\t" + "fabs 1,1\n\t" + "mtfsf 0x01,11\n\t" + "blr\n" +"2:" "bge- 6,3f\n\t" + "fsub 1,1,13\n\t" + "fadd 1,1,13\n\t" + "fnabs 1,1\n" +"3:" "mtfsf 0x01,11\n\t" + "blr\n\t" + "# friz == trunc\n" +"friz:" "mffs 11\n\t" +#ifdef __powerpc64__ + "lfd 13,8b@toc(2)\n\t" +#else + "mflr 11\n\t" + "bcl 20,31,1f\n" +"1:" "mflr 9\n\t" + "addis 9,9,8b-1b@ha\n\t" + "lfs 13,8b-1b@l(9)\n\t" + "mtlr 11\n\t" +#endif + "fabs 0,1\n\t" + "fsub 12,13,13\n\t" + "fcmpu 7,0,13\n\t" + "fcmpu 6,1,12\n\t" + "bnllr- 7\n\t" + "mtfsfi 7,1\n\t" + "ble- 6,2f\n\t" + "fadd 1,1,13\n\t" + "fsub 1,1,13\n\t" + "fabs 1,1\n\t" + "mtfsf 0x01,11\n\t" + "blr\n" +"2:" "bge- 6,3f\n\t" + "fsub 1,1,13\n\t" + "fadd 1,1,13\n\t" + "fnabs 1,1\n" +"3:" "mtfsf 0x01,11\n\t" + "blr\n\t" + "# frin == round\n" +"frin:" "mffs 11\n\t" +#ifdef __powerpc64__ + "lfd 13,8b@toc(2)\n\t" +#else + "mflr 11\n\t" + "bcl 20,31,1f\n" +"1:" "mflr 9\n\t" + "addis 9,9,8b-1b@ha\n\t" + "addi 9,9,8b-1b@l\n\t" + "mtlr 11\n\t" + "lfs 13,0(9)\n\t" +#endif + "fabs 0,1\n\t" + "fsub 12,13,13\n\t" + "fcmpu 7,0,13\n\t" + "fcmpu 6,1,12\n\t" + "bnllr- 7\n\t" + "mtfsfi 7,1\n\t" +#ifdef __powerpc64__ + "lfd 10,9b@toc(2)\n\t" +#else + "lfs 10,9b-8b(9)\n\t" +#endif + "ble- 6,2f\n\t" + "fadd 1,1,10\n\t" + "fadd 1,1,13\n\t" + "fsub 1,1,13\n\t" + "fabs 1,1\n\t" + "mtfsf 0x01,11\n\t" + "blr\n" +"2:" "fsub 9,1,10\n\t" + "bge- 6,3f\n\t" + "fsub 1,9,13\n\t" + "fadd 1,1,13\n\t" + "fnabs 1,1\n" +"3:" "mtfsf 0x01,11\n\t" + "blr\n\t" + "# frim == floor\n" +"frim:" "mffs 11\n\t" +#ifdef __powerpc64__ + "lfd 13,8b@toc(2)\n\t" +#else + "mflr 11\n\t" + "bcl 20,31,1f\n" +"1:" "mflr 9\n\t" + "addis 9,9,8b-1b@ha\n\t" + "lfs 13,8b-1b@l(9)\n\t" + "mtlr 11\n\t" +#endif + "fabs 0,1\n\t" + "fsub 12,13,13\n\t" + "fcmpu 7,0,13\n\t" + "fcmpu 6,1,12\n\t" + "bnllr- 7\n\t" + "mtfsfi 7,3\n\t" + "ble- 6,2f\n\t" + "fadd 1,1,13\n\t" + "fsub 1,1,13\n\t" + "fabs 1,1\n\t" + "mtfsf 0x01,11\n\t" + "blr\n" +"2:" "bge- 6,3f\n\t" + "fsub 1,1,13\n\t" + "fadd 1,1,13\n\t" + "fnabs 1,1\n" +"3:" "mtfsf 0x01,11\n\t" + "blr\n"); + +#ifdef __powerpc64__ +#define m1 0x5555555555555555L +#define m2 0x3333333333333333L +#define m3 0x0f0f0f0f0f0f0f0fL +#else +#define m1 0x55555555 +#define m2 0x33333333 +#define m3 0x0f0f0f0f +#endif + +static inline unsigned long +popcntb (unsigned long n) +{ + n -= (n >> 1) & m1; + n = (n & m2) + ((n >> 2) & m2); + n = (n + (n >> 4)) & m3; + return n; +} + +static void +catch_sigill (int signal, struct sigcontext *ctx) +{ + unsigned int insn = *(unsigned int *) (ctx->regs->nip); +#ifdef __powerpc64__ + if ((insn & 0xfc1f07ff) == 0x7c0005be) /* mftgpr */ + { + unsigned long *regs = (unsigned long *) ctx->regs; + unsigned fpr = (insn >> 11) & 0x1f; + unsigned gpr = (insn >> 21) & 0x1f; + regs[gpr] = regs[fpr + 0x30]; + ctx->regs->nip += 4; + return; + } + if ((insn & 0xfc1f07ff) == 0x7c0004be) /*mffgpr */ + { + unsigned long *regs = (unsigned long *) ctx->regs; + unsigned fpr = (insn >> 21) & 0x1f; + unsigned gpr = (insn >> 11) & 0x1f; + regs[fpr + 0x30] = regs[gpr]; + ctx->regs->nip += 4; + return; + } +#endif + if ((insn & 0xfc1f073f) == 0xfc000310) /* fri[pznm] */ + { +#ifdef __powerpc64__ + double *regs = (double *) (((char *) ctx->regs) + 0x30 * 8); + unsigned int *fpscr = (unsigned int *) (((char *) ctx->regs) + 0x50 * 8 + 4); +#else + double *regs = (double *) (((char *) ctx->regs) + 0x30 * 4); + unsigned int *fpscr = (unsigned int *) (((char *) ctx->regs) + 0x30 * 4 + 0x20 * 8 + 4); +#endif + unsigned dest = (insn >> 21) & 0x1f; + unsigned src = (insn >> 11) & 0x1f; + switch (insn & 0xc0) + { + case 0: + regs[dest] = frin (regs[src]); + break; + case 0x40: + regs[dest] = friz (regs[src]); + break; + case 0x80: + regs[dest] = frip (regs[src]); + break; + case 0xc0: + regs[dest] = frim (regs[src]); + break; + } + /* Update raised exceptions. */ + union { unsigned int i[2]; double d; } u; + asm volatile ("mffs %0" : "=f" (u.d)); + u.i[1] &= 0xfffe0000; /* Is this correct? */ + *fpscr |= u.i[1]; + ctx->regs->nip += 4; + return; + } + if ((insn & 0xfc00ffff) == 0x7c0000f4) /* popcntb */ + { + unsigned long *regs = (unsigned long *) ctx->regs; + unsigned dest = (insn >> 16) & 0x1f; + unsigned src = (insn >> 21) & 0x1f; + unsigned long res = 0; + int i; + + regs[dest] = popcntb (regs[src]); + ctx->regs->nip += 4; + return; + } + + struct sigaction sa; + sa.sa_handler = SIG_DFL; + sigemptyset (&sa.sa_mask); + sa.sa_flags = 0; + sigaction (signal, &sa, NULL); + raise (signal); +} + +static void +__attribute__ ((constructor)) +install_handler (void) +{ + struct sigaction sa; + sa.sa_handler = (void *) catch_sigill; + sigemptyset (&sa.sa_mask); + sa.sa_flags = SA_RESTART; + sigaction (SIGILL, &sa, NULL); +} diff --git a/sources b/sources index fea5433..56c580f 100644 --- a/sources +++ b/sources @@ -1,2 +1 @@ b67b22b428ed183148d1344da6d22ea9 glibc-2.18.tar.gz -80983ab3cd4eee313e778fcf5fbc5e4f glibc-2.18-releng.tar.gz