* Makefile.in (clean): Remove non-existant regexp dir.

* collate.h: New header.
	(__collate_range_cmp): Declare.
	(__collate_load_error): Define.
	* glob.cc: Pull in latest version from FreeBSD.  Simplify and reduce
	Cygwin-specific changes.
	* regex/regcomp.c: Include collate.h on Cygwin as well.
	(__collate_range_cmp): Move from here...
	* nlsfuncs.cc (__collate_range_cmp): ...to here.

	* miscfuncs.cc (thread_wrapper): Fix typo in comment.
	(CygwinCreateThread): Take dead zone of Windows stack into account.
	Change the way how the stack is commited and how to handle guardpages.
	Explain how and why.
	* thread.h (PTHREAD_DEFAULT_STACKSIZE): Change definition.  Explain why.
This commit is contained in:
Corinna Vinschen 2012-02-13 13:12:37 +00:00
parent e633eaec08
commit d7bcd2a16f
8 changed files with 167 additions and 121 deletions

View File

@ -1,3 +1,22 @@
2012-02-13 Corinna Vinschen <corinna@vinschen.de>
* Makefile.in (clean): Remove non-existant regexp dir.
* collate.h: New header.
(__collate_range_cmp): Declare.
(__collate_load_error): Define.
* glob.cc: Pull in latest version from FreeBSD. Simplify and reduce
Cygwin-specific changes.
* regex/regcomp.c: Include collate.h on Cygwin as well.
(__collate_range_cmp): Move from here...
* nlsfuncs.cc (__collate_range_cmp): ...to here.
* miscfuncs.cc (thread_wrapper): Fix typo in comment.
(CygwinCreateThread): Take dead zone of Windows stack into account.
Change the way how the stack is commited and how to handle guardpages.
Explain how and why.
* thread.h (PTHREAD_DEFAULT_STACKSIZE): Change definition. Explain why.
2012-02-12 Yaakov Selkowitz <yselkowitz@users.sourceforg.net> 2012-02-12 Yaakov Selkowitz <yselkowitz@users.sourceforg.net>
* include/pthread.h: Include time.h as required by POSIX. * include/pthread.h: Include time.h as required by POSIX.

View File

@ -383,7 +383,7 @@ uninstall-man:
done done
clean: clean:
-rm -f *.o *.dll *.dbg *.a *.exp junk *.base version.cc regexp/*.o winver_stamp *.exe *.d *stamp* *_magic.h sigfe.s cygwin.def globals.h $(srcdir)/tlsoffsets.h $(srcdir)/devices.cc -rm -f *.o *.dll *.dbg *.a *.exp junk *.base version.cc winver_stamp *.exe *.d *stamp* *_magic.h sigfe.s cygwin.def globals.h $(srcdir)/tlsoffsets.h $(srcdir)/devices.cc
-@$(MAKE) -C $(bupdir)/cygserver libclean -@$(MAKE) -C $(bupdir)/cygserver libclean
maintainer-clean realclean: clean maintainer-clean realclean: clean

23
winsup/cygwin/collate.h Normal file
View File

@ -0,0 +1,23 @@
/* collate.h: Internal BSD libc header, used in glob and regcomp, for instance.
Copyright 2012 Red Hat, Inc.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#ifdef __cplusplus
extern "C" {
#endif
/* We never have a collate load error. */
const int __collate_load_error = 0;
int __collate_range_cmp (int c1, int c2);
#ifdef __cplusplus
};
#endif

View File

@ -33,9 +33,8 @@
#if defined(LIBC_SCCS) && !defined(lint) #if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93"; static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93";
#endif /* LIBC_SCCS and not lint */ #endif /* LIBC_SCCS and not lint */
#ifdef __CYGWIN #include <sys/cdefs.h>
__FBSDID("$FreeBSD: /repoman/r/ncvs/src/lib/libc/gen/glob.c,v 1.25 2006/06/05 18:22:13 delphij Exp $"); __FBSDID("$FreeBSD: src/lib/libc/gen/glob.c,v 1.28 2010/05/12 17:44:00 gordon Exp $");
#endif
/* /*
* glob(3) -- a superset of the one defined in POSIX 1003.2. * glob(3) -- a superset of the one defined in POSIX 1003.2.
@ -72,35 +71,45 @@ __FBSDID("$FreeBSD: /repoman/r/ncvs/src/lib/libc/gen/glob.c,v 1.25 2006/06/05 18
* 3. State-dependent encodings are not currently supported. * 3. State-dependent encodings are not currently supported.
*/ */
#ifdef __CYGWIN__
#include "winsup.h" #include "winsup.h"
#endif
#include <sys/param.h>
#include <sys/stat.h>
#include <ctype.h> #include <ctype.h>
#include <dirent.h> #include <dirent.h>
#include <errno.h>
#include <glob.h> #include <glob.h>
#include <limits.h>
#include <pwd.h> #include <pwd.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <unistd.h> #include <unistd.h>
#include <wchar.h> #include <wchar.h>
//#include "collate.h" #include "collate.h"
#include "cygerrno.h" #ifdef __CYGWIN__
#include "security.h" #include <wctype.h>
#include "path.h" #include "path.h"
#include "fhandler.h" #include "fhandler.h"
#include "dtable.h" #include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include "perprocess.h"
#include "cygwin/version.h" #include "cygwin/version.h"
#ifndef ARG_MAX #define getpwuid(uid) getpwuid32 (uid)
#define ARG_MAX 32000 /* See CreateProcess */ #define getuid() getuid32 ()
#endif #define issetugid() (cygheap->user.issetuid ())
#undef MAXPATHLEN #define stat __stat64
#define MAXPATHLEN 16384
#define CCHAR(c) (ignore_case_with_glob ? towlower (CHAR (c)) : CHAR (c))
#define Cchar(c) (ignore_case_with_glob ? towlower (c) : (c))
#endif
#define DOLLAR '$' #define DOLLAR '$'
#define DOT '.' #define DOT '.'
@ -154,13 +163,13 @@ typedef char Char;
static int compare(const void *, const void *); static int compare(const void *, const void *);
static int g_Ctoc(const Char *, char *, size_t); static int g_Ctoc(const Char *, char *, size_t);
static int g_lstat(Char *, struct __stat64 *, glob_t *); static int g_lstat(Char *, struct stat *, glob_t *);
static DIR *g_opendir(Char *, glob_t *); static DIR *g_opendir(Char *, glob_t *);
static Char *g_strchr(Char *, wchar_t); static const Char *g_strchr(const Char *, wchar_t);
#ifdef notdef #ifdef notdef
static Char *g_strcat(Char *, const Char *); static Char *g_strcat(Char *, const Char *);
#endif #endif
static int g_stat(Char *, struct __stat64 *, glob_t *); static int g_stat(Char *, struct stat *, glob_t *);
static int glob0(const Char *, glob_t *, size_t *); static int glob0(const Char *, glob_t *, size_t *);
static int glob1(Char *, glob_t *, size_t *); static int glob1(Char *, glob_t *, size_t *);
static int glob2(Char *, Char *, Char *, Char *, glob_t *, size_t *); static int glob2(Char *, Char *, Char *, Char *, glob_t *, size_t *);
@ -259,7 +268,7 @@ globexp1(const Char *pattern, glob_t *pglob, size_t *limit)
if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
return glob0(pattern, pglob, limit); return glob0(pattern, pglob, limit);
while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL) while ((ptr = g_strchr(ptr, LBRACE)) != NULL)
if (!globexp2(ptr, pattern, pglob, &rv, limit)) if (!globexp2(ptr, pattern, pglob, &rv, limit))
return rv; return rv;
@ -403,11 +412,11 @@ globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob)
* we're not running setuid or setgid) and then trying * we're not running setuid or setgid) and then trying
* the password file * the password file
*/ */
if (cygheap->user.issetuid() != 0 || if (issetugid() != 0 ||
(h = getenv("HOME")) == NULL) { (h = getenv("HOME")) == NULL) {
if (((h = getlogin()) != NULL && if (((h = getlogin()) != NULL &&
(pwd = getpwnam(h)) != NULL) || (pwd = getpwnam(h)) != NULL) ||
(pwd = getpwuid32(getuid32())) != NULL) (pwd = getpwuid(getuid())) != NULL)
h = pwd->pw_dir; h = pwd->pw_dir;
else else
return pattern; return pattern;
@ -448,7 +457,7 @@ glob0(const Char *pattern, glob_t *pglob, size_t *limit)
const Char *qpatnext; const Char *qpatnext;
int err; int err;
size_t oldpathc; size_t oldpathc;
Char c, *bufnext, patbuf[MAXPATHLEN]; Char *bufnext, c, patbuf[MAXPATHLEN];
qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob); qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob);
oldpathc = pglob->gl_pathc; oldpathc = pglob->gl_pathc;
@ -462,7 +471,7 @@ glob0(const Char *pattern, glob_t *pglob, size_t *limit)
if (c == NOT) if (c == NOT)
++qpatnext; ++qpatnext;
if (*qpatnext == EOS || if (*qpatnext == EOS ||
g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) { g_strchr(qpatnext+1, RBRACKET) == NULL) {
*bufnext++ = LBRACKET; *bufnext++ = LBRACKET;
if (c == NOT) if (c == NOT)
--qpatnext; --qpatnext;
@ -556,7 +565,7 @@ static int
glob2(Char *pathbuf, Char *pathend, Char *pathend_last, Char *pattern, glob2(Char *pathbuf, Char *pathend, Char *pathend_last, Char *pattern,
glob_t *pglob, size_t *limit) glob_t *pglob, size_t *limit)
{ {
struct __stat64 sb; struct stat sb;
Char *p, *q; Char *p, *q;
int anymeta; int anymeta;
@ -625,6 +634,8 @@ glob3(Char *pathbuf, Char *pathend, Char *pathend_last,
* assigned, below, to two functions which are prototyped in glob.h * assigned, below, to two functions which are prototyped in glob.h
* and dirent.h as taking pointers to differently typed opaque * and dirent.h as taking pointers to differently typed opaque
* structures. * structures.
* CYGWIN: Needs prototype and subsequently wild casting to avoid
* compiler error.
*/ */
struct dirent *(*readdirfunc)(void *); struct dirent *(*readdirfunc)(void *);
@ -642,7 +653,7 @@ glob3(Char *pathbuf, Char *pathend, Char *pathend_last,
pglob->gl_flags & GLOB_ERR) pglob->gl_flags & GLOB_ERR)
return (GLOB_ABORTED); return (GLOB_ABORTED);
} }
return((pglob->gl_flags & GLOB_ERR) ? GLOB_ABORTED : 0); return(0);
} }
err = 0; err = 0;
@ -786,41 +797,23 @@ match(Char *name, Char *pat, Char *patend)
return(0); return(0);
if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
++pat; ++pat;
if (ignore_case_with_glob)
{
while (((c = *pat++) & M_MASK) != M_END) while (((c = *pat++) & M_MASK) != M_END)
if ((*pat & M_MASK) == M_RNG) { if ((*pat & M_MASK) == M_RNG) {
if (tolower(c) <= tolower(k) && tolower(k) <= tolower(pat[1])) if (__collate_load_error ?
ok = 1; CCHAR(c) <= CCHAR(k) && CCHAR(k) <= CCHAR(pat[1]) :
pat += 2; __collate_range_cmp(CCHAR(c), CCHAR(k)) <= 0
} else if (tolower(c) == tolower(k)) && __collate_range_cmp(CCHAR(k), CCHAR(pat[1])) <= 0
ok = 1; )
}
else
{
while (((c = *pat++) & M_MASK) != M_END)
if ((*pat & M_MASK) == M_RNG) {
if (c <= k && k <= pat[1])
ok = 1; ok = 1;
pat += 2; pat += 2;
} else if (c == k) } else if (c == k)
ok = 1; ok = 1;
}
if (ok == negate_range) if (ok == negate_range)
return(0); return(0);
break; break;
default: default:
if (ignore_case_with_glob) if (Cchar(*name++) != Cchar(c))
{
if (tolower(*name) != tolower(c))
return(0); return(0);
++name;
}
else
{
if (*name++ != c)
return(0);
}
break; break;
} }
} }
@ -881,8 +874,18 @@ stat32_to_stat64 (struct __stat32 *src, struct __stat64 *dst)
dst->st_blocks = src->st_blocks; dst->st_blocks = src->st_blocks;
} }
#define CYGWIN_gl_stat(sfptr) \
({ int ret; \
struct __stat32 lsb; \
if (CYGWIN_VERSION_CHECK_FOR_USING_BIG_TYPES) \
ret = (*pglob->sfptr) (buf, sb); \
else if (!(ret = (*pglob->sfptr) (buf, (struct __stat64 *) &lsb))) \
stat32_to_stat64 (&lsb, sb); \
ret; \
})
static int static int
g_lstat(Char *fn, struct __stat64 *sb, glob_t *pglob) g_lstat(Char *fn, struct stat *sb, glob_t *pglob)
{ {
char buf[MAXPATHLEN]; char buf[MAXPATHLEN];
@ -890,22 +893,13 @@ g_lstat(Char *fn, struct __stat64 *sb, glob_t *pglob)
errno = ENAMETOOLONG; errno = ENAMETOOLONG;
return (-1); return (-1);
} }
if (pglob->gl_flags & GLOB_ALTDIRFUNC) { if (pglob->gl_flags & GLOB_ALTDIRFUNC)
struct __stat32 lsb; return CYGWIN_gl_stat (gl_lstat);
int ret;
if (CYGWIN_VERSION_CHECK_FOR_USING_BIG_TYPES)
ret = (*pglob->gl_lstat)(buf, sb);
else if (!(ret = (*pglob->gl_lstat)(buf,
(struct __stat64 *)&lsb)))
stat32_to_stat64 (&lsb, sb);
return ret;
}
return(lstat64(buf, sb)); return(lstat64(buf, sb));
} }
static int static int
g_stat(Char *fn, struct __stat64 *sb, glob_t *pglob) g_stat(Char *fn, struct stat *sb, glob_t *pglob)
{ {
char buf[MAXPATHLEN]; char buf[MAXPATHLEN];
@ -913,22 +907,13 @@ g_stat(Char *fn, struct __stat64 *sb, glob_t *pglob)
errno = ENAMETOOLONG; errno = ENAMETOOLONG;
return (-1); return (-1);
} }
if (pglob->gl_flags & GLOB_ALTDIRFUNC) { if (pglob->gl_flags & GLOB_ALTDIRFUNC)
struct __stat32 lsb; return CYGWIN_gl_stat (gl_stat);
int ret;
if (CYGWIN_VERSION_CHECK_FOR_USING_BIG_TYPES)
ret = (*pglob->gl_stat)(buf, sb);
else if (!(ret = (*pglob->gl_stat)(buf,
(struct __stat64 *)&lsb)))
stat32_to_stat64 (&lsb, sb);
return ret;
}
return(stat64(buf, sb)); return(stat64(buf, sb));
} }
static Char * static const Char *
g_strchr(Char *str, wchar_t ch) g_strchr(const Char *str, wchar_t ch)
{ {
do { do {

View File

@ -527,7 +527,7 @@ thread_wrapper (VOID *arg)
xorl %%ebp, %%ebp # Set ebp to 0 \n\ xorl %%ebp, %%ebp # Set ebp to 0 \n\
# Make gcc 3.x happy and align the stack so that it is \n\ # Make gcc 3.x happy and align the stack so that it is \n\
# 16 byte aligned right before the final call opcode. \n\ # 16 byte aligned right before the final call opcode. \n\
andl $-16, %%esp # 16 bit align \n\ andl $-16, %%esp # 16 byte align \n\
addl $-12, %%esp # 12 bytes + 4 byte arg = 16 \n\ addl $-12, %%esp # 12 bytes + 4 byte arg = 16 \n\
# Now we moved to the new stack. Save thread func address\n\ # Now we moved to the new stack. Save thread func address\n\
# and thread arg on new stack \n\ # and thread arg on new stack \n\
@ -578,11 +578,17 @@ CygwinCreateThread (LPTHREAD_START_ROUTINE thread_func, PVOID thread_arg,
} }
else else
{ {
char *commitaddr;
/* If not, we have to create the stack here. */ /* If not, we have to create the stack here. */
real_stacksize = roundup2 (stacksize, wincap.page_size ()); real_stacksize = roundup2 (stacksize, wincap.page_size ());
real_guardsize = roundup2 (guardsize, wincap.page_size ()); real_guardsize = roundup2 (guardsize, wincap.page_size ());
/* Add the guardsize to the stacksize */ /* Add the guardsize to the stacksize */
real_stacksize += real_guardsize; real_stacksize += real_guardsize;
/* If we use the default Windows guardpage method, we have to take
the 2 pages dead zone into account. */
if (real_guardsize == wincap.page_size ())
real_stacksize += 2 * wincap.page_size ();
/* Now roundup the result to the next allocation boundary. */ /* Now roundup the result to the next allocation boundary. */
real_stacksize = roundup2 (real_stacksize, real_stacksize = roundup2 (real_stacksize,
wincap.allocation_granularity ()); wincap.allocation_granularity ());
@ -596,10 +602,33 @@ CygwinCreateThread (LPTHREAD_START_ROUTINE thread_func, PVOID thread_arg,
PAGE_READWRITE); PAGE_READWRITE);
if (!real_stackaddr) if (!real_stackaddr)
return NULL; return NULL;
/* Set up committed region. In contrast to the OS we commit 64K and /* Set up committed region. Two cases: */
set up just a single guard page at the end. */ if (real_guardsize != wincap.page_size ())
char *commitaddr = (char *) real_stackaddr {
+ real_stacksize /* If guardsize is set to something other than the page size, we
commit the entire stack and, if guardsize is > 0, we set up a
POSIX guardpage. We don't set up a Windows guardpage. */
if (!VirtualAlloc (real_stackaddr, real_guardsize, MEM_COMMIT,
PAGE_NOACCESS))
goto err;
commitaddr = (char *) real_stackaddr + real_guardsize;
if (!VirtualAlloc (commitaddr, real_stacksize - real_guardsize,
MEM_COMMIT, PAGE_READWRITE))
goto err;
}
else
{
/* If guardsize is exactly the page_size, we can assume that the
application will behave Windows conformant in terms of stack usage.
We can especially assume that it never allocates more than one
page at a time (alloca/_chkstk). Therefore, this is the default
case which allows a Windows compatible stack setup with a
reserved region, a guard page, and a commited region. We don't
need to set up a POSIX guardpage since Windows already handles
stack overflow: Trying to extend the stack into the last three
pages of the stack results in a SEGV.
We always commit 64K here, starting with the guardpage. */
commitaddr = (char *) real_stackaddr + real_stacksize
- wincap.allocation_granularity (); - wincap.allocation_granularity ();
if (!VirtualAlloc (commitaddr, wincap.page_size (), MEM_COMMIT, if (!VirtualAlloc (commitaddr, wincap.page_size (), MEM_COMMIT,
PAGE_READWRITE | PAGE_GUARD)) PAGE_READWRITE | PAGE_GUARD))
@ -609,15 +638,7 @@ CygwinCreateThread (LPTHREAD_START_ROUTINE thread_func, PVOID thread_arg,
- wincap.page_size (), MEM_COMMIT, - wincap.page_size (), MEM_COMMIT,
PAGE_READWRITE)) PAGE_READWRITE))
goto err; goto err;
/* If the guardsize is != 0 (which is the default), set up a POSIX }
guardpage at the end of the stack. This isn't the same as the
Windows guardpage, which is used to convert reserved stack to
commited stack if necessary. Rather, the POSIX guardpage consists
of one or more memory pages with NOACCESS protection. It's supposed
to safeguard memory areas beyond the stack against stack overflow. */
if (real_guardsize)
VirtualAlloc (real_stackaddr, real_guardsize, MEM_COMMIT,
PAGE_NOACCESS);
wrapper_arg->stackaddr = (char *) real_stackaddr; wrapper_arg->stackaddr = (char *) real_stackaddr;
wrapper_arg->stackbase = (char *) real_stackaddr + real_stacksize; wrapper_arg->stackbase = (char *) real_stackaddr + real_stacksize;
wrapper_arg->commitaddr = commitaddr; wrapper_arg->commitaddr = commitaddr;

View File

@ -1192,6 +1192,15 @@ strcoll (const char *s1, const char *s2)
return ret - CSTR_EQUAL; return ret - CSTR_EQUAL;
} }
/* BSD. Used in glob.cc and regcomp.c, for instance. */
extern "C" int
__collate_range_cmp (int c1, int c2)
{
char s1[2] = { c1, '\0' };
char s2[2] = { c2, '\0' };
return strcoll (s1, s2);
}
extern "C" size_t extern "C" size_t
wcsxfrm (wchar_t *ws1, const wchar_t *ws2, size_t wsn) wcsxfrm (wchar_t *ws1, const wchar_t *ws2, size_t wsn)
{ {

View File

@ -55,9 +55,7 @@ __FBSDID("$FreeBSD: src/lib/libc/regex/regcomp.c,v 1.36 2007/06/11 03:05:54 delp
#include <wchar.h> #include <wchar.h>
#include <wctype.h> #include <wctype.h>
#ifndef __CYGWIN__
#include "collate.h" #include "collate.h"
#endif
#include "utils.h" #include "utils.h"
#include "regex2.h" #include "regex2.h"
@ -771,17 +769,6 @@ p_bracket(struct parse *p)
EMIT(OANYOF, (int)(cs - p->g->sets)); EMIT(OANYOF, (int)(cs - p->g->sets));
} }
#ifdef __CYGWIN__
/* This function is usually part of FreeBSD's libc. */
int
__collate_range_cmp(int c1, int c2)
{
char s1[2] = { c1, '\0' };
char s2[2] = { c2, '\0' };
return strcoll (s1, s2);
}
#endif
/* /*
- p_b_term - parse one term of a bracketed character list - p_b_term - parse one term of a bracketed character list
== static void p_b_term(struct parse *p, cset *cs); == static void p_b_term(struct parse *p, cset *cs);

View File

@ -16,10 +16,12 @@ details. */
#define WRITE_LOCK 1 #define WRITE_LOCK 1
#define READ_LOCK 2 #define READ_LOCK 2
/* Default is a 1 Megs stack with a 4K guardpage. Since the pthread stacksize /* Default is a 1 Megs stack with a 4K guardpage. The pthread stacksize
does not include the guardpage size, but we don't want to waste another 64K, does not include the guardpage size, so we subtract the default guardpage
subtract the default guardpage size from the stacksize. */ size. Additionally, the Windows stack handling disallows to use the last
#define PTHREAD_DEFAULT_STACKSIZE (1024 * 1024 - wincap.page_size ()) two pages as guard page (tested on XP and W7). That results in a zone of
three pages which have to be subtract to get the actual stack size. */
#define PTHREAD_DEFAULT_STACKSIZE (1024 * 1024 - 3 * wincap.page_size ())
#define PTHREAD_DEFAULT_GUARDSIZE (wincap.page_size ()) #define PTHREAD_DEFAULT_GUARDSIZE (wincap.page_size ())
#include <pthread.h> #include <pthread.h>