Bug 31310

Summary: pthread broken with KVA_PAGES=512
Product: Base System Reporter: justin <justin>
Component: kernAssignee: freebsd-bugs (Nobody) <bugs>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 4.4-STABLE   
Hardware: Any   
OS: Any   

Description justin 2001-10-16 09:20:00 UTC
KVA_PAGES in kernel config is set to 512, and I had 'make world'
to update /usr/lib.

When I run any program that use pthread (linked with libc_r), 
it prints:

 
Fatal error 'Cannot allocate red zone for initial thread' at line ? in file
/usr/src/lib/libc_r/uthread/uthread_init.c (errno = ?)

Abort trap (core dumped)
 

I didn't have this problem on 4.4-RC0 with ldscript.i386 and pmap.h 
patched as the following to enlarge kernel address space to 2G.

Index: conf/ldscript.i386
===================================================================
RCS file: /home/ncvs/src/sys/conf/ldscript.i386,v
retrieving revision 1.4
diff -u -r1.4 ldscript.i386
--- conf/ldscript.i386	2000/01/11 15:35:16	1.4
+++ conf/ldscript.i386	2001/04/02 16:07:18
@@ -6,7 +6,7 @@
 SECTIONS
 {
   /* Read-only sections, merged into text segment: */
-  . = 0xc0100000 + SIZEOF_HEADERS;
+  . = 0x80100000 + SIZEOF_HEADERS;
   .interp     : { *(.interp) 	}
   .hash          : { *(.hash)		}
   .dynsym        : { *(.dynsym)		}
Index: i386/include/pmap.h
===================================================================
RCS file: /home/ncvs/src/sys/i386/include/pmap.h,v
retrieving revision 1.70
diff -u -r1.70 pmap.h
--- i386/include/pmap.h	2000/11/30 01:53:02	1.70
+++ i386/include/pmap.h	2001/04/02 16:07:18
@@ -92,9 +92,9 @@
 #endif
 #ifndef NKPDE
 #ifdef SMP
-#define NKPDE			254	/* addressable number of page
tables/pde's */
+#define NKPDE			510	/* addressable number of page
tables/pde's */
 #else
-#define NKPDE			255	/* addressable number of page
tables/pde's */
+#define NKPDE			511	/* addressable number of page
tables/pde's */
 #endif	/* SMP */
 #endif

How-To-Repeat: N/A
Comment 1 Jason Evans 2001-10-16 19:01:39 UTC
On Tue, Oct 16, 2001 at 04:16:51PM +0800, justin@skysoft.com.tw wrote:
> 
> >Description:
> KVA_PAGES in kernel config is set to 512, and I had 'make world'
> to update /usr/lib.
> 
> When I run any program that use pthread (linked with libc_r), 
> it prints:
> 
>  
> Fatal error 'Cannot allocate red zone for initial thread' at line ? in file
> /usr/src/lib/libc_r/uthread/uthread_init.c (errno = ?)
> 
> Abort trap (core dumped)
>  
> 
> I didn't have this problem on 4.4-RC0 with ldscript.i386 and pmap.h 
> patched as the following to enlarge kernel address space to 2G.

I'm not sure I understand what you're doing, so let me try to summarize my
understanding before guessing what the problem is.  It sounds like you are
changing the amount of address space reserved for the kernel, which affects
where the userland stack is mapped.  Look in
src/lib/libc_r/uthread/uthread_init.c for the mmap() call that creates the
red zone:

		/*
		 * Create a red zone below the main stack.  All other stacks are
		 * constrained to a maximum size by the paramters passed to
		 * mmap(), but this stack is only limited by resource limits, so
		 * this stack needs an explicitly mapped red zone to protect the
		 * thread stack that is just beyond.
		 */
		if (mmap((void *) USRSTACK - PTHREAD_STACK_INITIAL -
		    PTHREAD_STACK_GUARD, PTHREAD_STACK_GUARD, 0, MAP_ANON,
		    -1, 0) == MAP_FAILED)
			PANIC("Cannot allocate red zone for initial thread");

The code depends on the USRSTACK macro when determining where to create the
red zone, and I suspect that its value is somewhere in kernel memory in
your case.

From src/sys/i386/include/vmparam.h:

#define	VM_MAXUSER_ADDRESS	VADDR(UMAXPTDI, UMAXPTEOFF)

#define	USRSTACK		VM_MAXUSER_ADDRESS

Please let me know if after further diagnostic effort you discover this to
be an actual problem in libc_r.

Jason
Comment 2 justin 2001-10-17 08:18:25 UTC
Thanks to Jason.

I solved this problem by adding -DKVA_PAGES=512 in CFLAGS at etc/make.conf

Libc_r include /usr/include/machine/pmap.h to determine 
USRSTACK, but kernel configuration of KVA_PAGES is defined in
/usr/src/sys/compile/XXXX/opt_global.h, so libc_r use wrong value of
USRSTACK.

Once after KVA_PAGES is documented in LINT, a note on this would be helpful
for those who need pthread and have large memory.

By the way, FreeBSD prior to 4.4-STABLE, including 4.4-RC0, seem to have
wrong pmap.h that can't produce correct USRSTACK from KVA_PAGES macro. If a
person want to upgrade to 4.4-STABLE and change KVA_PAGES, maybe he needs to
make world twice to have correct pmap.h in /usr/include.
Comment 3 Bruce Evans 2001-10-17 08:23:15 UTC
On Tue, 16 Oct 2001, Jason Evans wrote:

>  I'm not sure I understand what you're doing, so let me try to summarize my
>  understanding before guessing what the problem is.  It sounds like you are
>  changing the amount of address space reserved for the kernel, which affects
>  where the userland stack is mapped.  Look in
>  src/lib/libc_r/uthread/uthread_init.c for the mmap() call that creates the
>  red zone:
>
>  		/*
>  		 * Create a red zone below the main stack.  All other stacks are
>  		 * constrained to a maximum size by the paramters passed to
>  		 * mmap(), but this stack is only limited by resource limits, so
>  		 * this stack needs an explicitly mapped red zone to protect the
>  		 * thread stack that is just beyond.
>  		 */
>  		if (mmap((void *) USRSTACK - PTHREAD_STACK_INITIAL -
>  		    PTHREAD_STACK_GUARD, PTHREAD_STACK_GUARD, 0, MAP_ANON,
>  		    -1, 0) == MAP_FAILED)
>  			PANIC("Cannot allocate red zone for initial thread");
>
>  The code depends on the USRSTACK macro when determining where to create the
>  red zone, and I suspect that its value is somewhere in kernel memory in
>  your case.
>
>  From src/sys/i386/include/vmparam.h:
>
>  #define	VM_MAXUSER_ADDRESS	VADDR(UMAXPTDI, UMAXPTEOFF)
>
>  #define	USRSTACK		VM_MAXUSER_ADDRESS
>
>  Please let me know if after further diagnostic effort you discover this to
>  be an actual problem in libc_r.

Code like this (actually mainly bogus definitions of non-constants as
constant in <sys/param.h>) is very broken.  USRSTACK depends on the
kernel option KVA_PAGES.  Userland can't see kernel options headers,
so USRSTACK should not be visible in userland.  But i386/include/param.h
provides a bogus default for KVA_PAGES and consequently USRSTACK to
move the breakage from compile time to run time.

Some other bogus non-constant constants:
- OPEN_MAX and CHILD_MAX.
- PAGE_SIZE and pgtok() leaked out to userland a long time ago, desipite
  the existence of syscall and a sysctl to insulate them.  PAGE_SIZE is
  now an option on ia64's.
- UPAGES.
- MAXDSIZE, etc.  There are now tunables.  Anyone tuning them had better
  know all related magic addresses used deep in places like the above.
  There was some discussion of making them (variable) rlimits.  This stalled
  on the complications for knowing all the magic addresses and keeping them
  separate.

Bruce
Comment 4 Peter Wemm freebsd_committer freebsd_triage 2001-12-17 22:58:12 UTC
State Changed
From-To: open->closed

Committed to -current on 2001/10/26, and -stable on 2001/11/03. 
(See src/lib/libc_r/uthread/uthread_init.c and uthread_stack.c etc)