* 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>
* include/pthread.h: Include time.h as required by POSIX.

View File

@ -383,7 +383,7 @@ uninstall-man:
done
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
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)
static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93";
#endif /* LIBC_SCCS and not lint */
#ifdef __CYGWIN
__FBSDID("$FreeBSD: /repoman/r/ncvs/src/lib/libc/gen/glob.c,v 1.25 2006/06/05 18:22:13 delphij Exp $");
#endif
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/gen/glob.c,v 1.28 2010/05/12 17:44:00 gordon Exp $");
/*
* 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.
*/
#ifdef __CYGWIN__
#include "winsup.h"
#endif
#include <sys/param.h>
#include <sys/stat.h>
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <glob.h>
#include <limits.h>
#include <pwd.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wchar.h>
//#include "collate.h"
#include "collate.h"
#include "cygerrno.h"
#include "security.h"
#ifdef __CYGWIN__
#include <wctype.h>
#include "path.h"
#include "fhandler.h"
#include "dtable.h"
#include "cygheap.h"
#include "perprocess.h"
#include "cygwin/version.h"
#ifndef ARG_MAX
#define ARG_MAX 32000 /* See CreateProcess */
#endif
#define getpwuid(uid) getpwuid32 (uid)
#define getuid() getuid32 ()
#define issetugid() (cygheap->user.issetuid ())
#undef MAXPATHLEN
#define MAXPATHLEN 16384
#define stat __stat64
#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 DOT '.'
@ -154,19 +163,19 @@ typedef char Char;
static int compare(const void *, const void *);
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 Char *g_strchr(Char *, wchar_t);
static const Char *g_strchr(const Char *, wchar_t);
#ifdef notdef
static Char *g_strcat(Char *, const Char *);
#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 glob1(Char *, glob_t *, size_t *);
static int glob2(Char *, Char *, Char *, Char *, glob_t *, size_t *);
static int glob3(Char *, Char *, Char *, Char *, Char *, glob_t *, size_t *);
static int globextend(const Char *, glob_t *, size_t *);
static const Char *
static const Char *
globtilde(const Char *, Char *, size_t, glob_t *);
static int globexp1(const Char *, glob_t *, size_t *);
static int globexp2(const Char *, const Char *, glob_t *, int *, 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)
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))
return rv;
@ -387,8 +396,8 @@ globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob)
if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
return pattern;
/*
* Copy up to the end of the string or /
/*
* Copy up to the end of the string or /
*/
eb = &patbuf[patbuf_len - 1];
for (p = pattern + 1, h = (char *) patbuf;
@ -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
* the password file
*/
if (cygheap->user.issetuid() != 0 ||
if (issetugid() != 0 ||
(h = getenv("HOME")) == NULL) {
if (((h = getlogin()) != NULL &&
(pwd = getpwnam(h)) != NULL) ||
(pwd = getpwuid32(getuid32())) != NULL)
(pwd = getpwuid(getuid())) != NULL)
h = pwd->pw_dir;
else
return pattern;
@ -448,7 +457,7 @@ glob0(const Char *pattern, glob_t *pglob, size_t *limit)
const Char *qpatnext;
int err;
size_t oldpathc;
Char c, *bufnext, patbuf[MAXPATHLEN];
Char *bufnext, c, patbuf[MAXPATHLEN];
qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob);
oldpathc = pglob->gl_pathc;
@ -462,7 +471,7 @@ glob0(const Char *pattern, glob_t *pglob, size_t *limit)
if (c == NOT)
++qpatnext;
if (*qpatnext == EOS ||
g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) {
g_strchr(qpatnext+1, RBRACKET) == NULL) {
*bufnext++ = LBRACKET;
if (c == NOT)
--qpatnext;
@ -556,7 +565,7 @@ static int
glob2(Char *pathbuf, Char *pathend, Char *pathend_last, Char *pattern,
glob_t *pglob, size_t *limit)
{
struct __stat64 sb;
struct stat sb;
Char *p, *q;
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
* and dirent.h as taking pointers to differently typed opaque
* structures.
* CYGWIN: Needs prototype and subsequently wild casting to avoid
* compiler error.
*/
struct dirent *(*readdirfunc)(void *);
@ -642,7 +653,7 @@ glob3(Char *pathbuf, Char *pathend, Char *pathend_last,
pglob->gl_flags & GLOB_ERR)
return (GLOB_ABORTED);
}
return((pglob->gl_flags & GLOB_ERR) ? GLOB_ABORTED : 0);
return(0);
}
err = 0;
@ -786,41 +797,23 @@ match(Char *name, Char *pat, Char *patend)
return(0);
if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
++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 (tolower(c) <= tolower(k) && tolower(k) <= tolower(pat[1]))
ok = 1;
pat += 2;
} else if (tolower(c) == tolower(k))
ok = 1;
}
else
{
while (((c = *pat++) & M_MASK) != M_END)
if ((*pat & M_MASK) == M_RNG) {
if (c <= k && k <= pat[1])
ok = 1;
pat += 2;
if (__collate_load_error ?
CCHAR(c) <= CCHAR(k) && CCHAR(k) <= CCHAR(pat[1]) :
__collate_range_cmp(CCHAR(c), CCHAR(k)) <= 0
&& __collate_range_cmp(CCHAR(k), CCHAR(pat[1])) <= 0
)
ok = 1;
pat += 2;
} else if (c == k)
ok = 1;
}
ok = 1;
if (ok == negate_range)
return(0);
break;
default:
if (ignore_case_with_glob)
{
if (tolower(*name) != tolower(c))
return(0);
++name;
}
else
{
if (*name++ != c)
if (Cchar(*name++) != Cchar(c))
return(0);
}
break;
}
}
@ -881,8 +874,18 @@ stat32_to_stat64 (struct __stat32 *src, struct __stat64 *dst)
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
g_lstat(Char *fn, struct __stat64 *sb, glob_t *pglob)
g_lstat(Char *fn, struct stat *sb, glob_t *pglob)
{
char buf[MAXPATHLEN];
@ -890,22 +893,13 @@ g_lstat(Char *fn, struct __stat64 *sb, glob_t *pglob)
errno = ENAMETOOLONG;
return (-1);
}
if (pglob->gl_flags & GLOB_ALTDIRFUNC) {
struct __stat32 lsb;
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;
}
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
return CYGWIN_gl_stat (gl_lstat);
return(lstat64(buf, sb));
}
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];
@ -913,22 +907,13 @@ g_stat(Char *fn, struct __stat64 *sb, glob_t *pglob)
errno = ENAMETOOLONG;
return (-1);
}
if (pglob->gl_flags & GLOB_ALTDIRFUNC) {
struct __stat32 lsb;
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;
}
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
return CYGWIN_gl_stat (gl_stat);
return(stat64(buf, sb));
}
static Char *
g_strchr(Char *str, wchar_t ch)
static const Char *
g_strchr(const Char *str, wchar_t ch)
{
do {

View File

@ -527,7 +527,7 @@ thread_wrapper (VOID *arg)
xorl %%ebp, %%ebp # Set ebp to 0 \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\
andl $-16, %%esp # 16 bit align \n\
andl $-16, %%esp # 16 byte align \n\
addl $-12, %%esp # 12 bytes + 4 byte arg = 16 \n\
# Now we moved to the new stack. Save thread func address\n\
# and thread arg on new stack \n\
@ -578,11 +578,17 @@ CygwinCreateThread (LPTHREAD_START_ROUTINE thread_func, PVOID thread_arg,
}
else
{
char *commitaddr;
/* If not, we have to create the stack here. */
real_stacksize = roundup2 (stacksize, wincap.page_size ());
real_guardsize = roundup2 (guardsize, wincap.page_size ());
/* Add the guardsize to the stacksize */
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. */
real_stacksize = roundup2 (real_stacksize,
wincap.allocation_granularity ());
@ -596,28 +602,43 @@ CygwinCreateThread (LPTHREAD_START_ROUTINE thread_func, PVOID thread_arg,
PAGE_READWRITE);
if (!real_stackaddr)
return NULL;
/* Set up committed region. In contrast to the OS we commit 64K and
set up just a single guard page at the end. */
char *commitaddr = (char *) real_stackaddr
+ real_stacksize
- wincap.allocation_granularity ();
if (!VirtualAlloc (commitaddr, wincap.page_size (), MEM_COMMIT,
PAGE_READWRITE | PAGE_GUARD))
goto err;
commitaddr += wincap.page_size ();
if (!VirtualAlloc (commitaddr, wincap.allocation_granularity ()
- wincap.page_size (), MEM_COMMIT,
PAGE_READWRITE))
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);
/* Set up committed region. Two cases: */
if (real_guardsize != wincap.page_size ())
{
/* 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 ();
if (!VirtualAlloc (commitaddr, wincap.page_size (), MEM_COMMIT,
PAGE_READWRITE | PAGE_GUARD))
goto err;
commitaddr += wincap.page_size ();
if (!VirtualAlloc (commitaddr, wincap.allocation_granularity ()
- wincap.page_size (), MEM_COMMIT,
PAGE_READWRITE))
goto err;
}
wrapper_arg->stackaddr = (char *) real_stackaddr;
wrapper_arg->stackbase = (char *) real_stackaddr + real_stacksize;
wrapper_arg->commitaddr = commitaddr;

View File

@ -1192,6 +1192,15 @@ strcoll (const char *s1, const char *s2)
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
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 <wctype.h>
#ifndef __CYGWIN__
#include "collate.h"
#endif
#include "utils.h"
#include "regex2.h"
@ -771,17 +769,6 @@ p_bracket(struct parse *p)
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
== static void p_b_term(struct parse *p, cset *cs);

View File

@ -16,10 +16,12 @@ details. */
#define WRITE_LOCK 1
#define READ_LOCK 2
/* Default is a 1 Megs stack with a 4K guardpage. Since the pthread stacksize
does not include the guardpage size, but we don't want to waste another 64K,
subtract the default guardpage size from the stacksize. */
#define PTHREAD_DEFAULT_STACKSIZE (1024 * 1024 - wincap.page_size ())
/* Default is a 1 Megs stack with a 4K guardpage. The pthread stacksize
does not include the guardpage size, so we subtract the default guardpage
size. Additionally, the Windows stack handling disallows to use the last
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 ())
#include <pthread.h>