Discussion:
hipe segmentation fault
unknown
2006-04-03 02:40:14 UTC
Permalink
Any advice on what might be causing this seg fault? The same test works
fine on another machine with same OS & hardware.

[serge:~/tmp]$ erl
Erlang (BEAM) emulator version 5.4.13 [source] [hipe] [threads:0]

Eshell V5.4.13 (abort with ^G)
1> os:type().
{unix,linux}
2> os:version().
{2,6,9}
3> c(big, [native]).
{ok,big}
4> big:bang(600).
Segmentation fault
[serge:~/tmp]$ uname -a
Linux drp01dev.corp.idt.net 2.6.9-5.ELsmp #1 SMP Wed Jan 5 19:30:39 EST
2005 i686 i686 i386 GNU/Linux
[serge:~/tmp]$ cat /etc/redhat-release
Red Hat Enterprise Linux ES release 4 (Nahant)
$ ldd /usr/local/lib/erlang/erts-5.4.13/bin/beam
libdl.so.2 => /lib/libdl.so.2 (0x00a83000)
libm.so.6 => /lib/tls/libm.so.6 (0x00a89000)
libncurses.so.5 => /usr/lib/libncurses.so.5 (0x0017e000)
libpthread.so.0 => /lib/tls/libpthread.so.0 (0x00ac0000)
librt.so.1 => /lib/tls/librt.so.1 (0x00bb2000)
libc.so.6 => /lib/tls/libc.so.6 (0x00958000)
/lib/ld-linux.so.2 (0x0093f000)

Regards,

Serge
unknown
2006-04-03 09:02:07 UTC
Permalink
Post by unknown
Any advice on what might be causing this seg fault? The same test works
fine on another machine with same OS & hardware.
[serge:~/tmp]$ erl
Erlang (BEAM) emulator version 5.4.13 [source] [hipe] [threads:0]
Eshell V5.4.13 (abort with ^G)
1> os:type().
{unix,linux}
2> os:version().
{2,6,9}
3> c(big, [native]).
{ok,big}
4> big:bang(600).
Segmentation fault
[serge:~/tmp]$ uname -a
Linux drp01dev.corp.idt.net 2.6.9-5.ELsmp #1 SMP Wed Jan 5 19:30:39 EST
2005 i686 i686 i386 GNU/Linux
[serge:~/tmp]$ cat /etc/redhat-release
Red Hat Enterprise Linux ES release 4 (Nahant)
If the other machine has identical HW and SW, then I'd
have to suspect the HW, like memory going bad, PSU too
weak or giving up, or inadequate cooling.

We could try to reproduce the error using your test case
(if you can share it), but since you say it works on another
identical machine, I'm not really suspecting a bug in HiPE
at this point.

/Mikael

p.s. That 2.6.9-5.EL kernel is way out of date.
unknown
2006-04-03 14:30:15 UTC
Permalink
Ops... Sorry, this test case was taken from Rickard Green's post on
profiling P11B smp scheduling support. I wanted to run it on multi-cpu
host, and installed R10B-10 and P11B releases with and without hipe.

I don't think this problem is related to some memory corruption. This
is what I tried to do in order to diagnose the problem:

I recompiled erts with gcc's "-g -O0" options, and then:

$ ulimit -c unlimited
$ erl -emu_args
Executing: /usr/local/lib/erlang/erts-5.4.13/bin/beam
/usr/local/lib/erlang/erts-5.4.13/bin/beam -- -root
/usr/local/lib/erlang -progname erl -- -home /home/serge

Erlang (BEAM) emulator version 5.4.13 [source] [hipe] [threads:0]

Eshell V5.4.13 (abort with ^G)
1> c(big, [native]).
{ok,big}
2> big:bang(4).
Segmentation fault (core dumped)

$ gdb /usr/local/lib/erlang/erts-5.4.13/bin/beam core.18921
GNU gdb Red Hat Linux (6.1post-1.20040607.62rh)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...Using host
libthread_db library "/lib/tls/libthread_db.so.1".

Core was generated by `/usr/local/lib/erlang/erts-5.4.13/bin/beam --
-root /usr/local/lib/erlang -prog'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/libdl.so.2...done.
Loaded symbols for /lib/libdl.so.2
Reading symbols from /lib/tls/libm.so.6...done.
Loaded symbols for /lib/tls/libm.so.6
Reading symbols from /usr/lib/libncurses.so.5...done.
Loaded symbols for /usr/lib/libncurses.so.5
Reading symbols from /lib/tls/libpthread.so.0...done.
Loaded symbols for /lib/tls/libpthread.so.0
Reading symbols from /lib/tls/librt.so.1...done.
Loaded symbols for /lib/tls/librt.so.1
Reading symbols from /lib/tls/libc.so.6...done.
Loaded symbols for /lib/tls/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
#0 0x08aae41c in ?? ()
(gdb) bt
#0 0x08aae41c in ?? ()
#1 0x080f0f63 in x86_call_to_native () at hipe/hipe_x86_glue.S:42
#2 0x00000000 in ?? ()
(gdb)

...

Looking at hipe_x86_glue.S:42:

x86_call_to_native:
ENTER_FROM_C
/* get argument registers */
LOAD_ARG_REGS
/* call the target */
NSP_CALL(*P_NCALLEE(P)) <-- Failing here

I'm not sure what this call does, but maybe Mikael can give a clue.

Regards,

Serge
Post by unknown
Any advice on what might be causing this seg fault?
Did you forget to attach 'big.erl', or did you deliberately leave it
out? (that would at least give you some feedback on whether it happens
on other people's setups too)
Matthias
--
Serge Aleynikov
R&D Telecom, IDT Corp.
Tel: (973) 438-3436
Fax: (973) 438-1464
serge
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: big.erl
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20060403/318a02e5/attachment.ksh>
unknown
2006-04-03 15:08:34 UTC
Permalink
Post by unknown
Ops... Sorry, this test case was taken from Rickard Green's post
Oh, ok. I assumed 'big' was something you'd written. Anyway, I ran it
on two machines here without problems and saw nothing special:

Linux antilipe 2.6.12.1 #3 Wed Jan 11 16:25:06 CET 2006 i686 GNU/Linux
tmp >erl
Erlang (BEAM) emulator version 5.4.13 [source] [hipe]

Eshell V5.4.13 (abort with ^G)
1> c(big, [native]).
{ok,big}
2> big:bang(4).
2.30000e-5

and

Linux cors 2.4.27 #5 Tue Feb 15 15:15:03 CET 2005 i686 GNU/Linux
matthias:/tmp$ erl
Erlang (BEAM) emulator version 5.4.13 [source] [hipe]

Eshell V5.4.13 (abort with ^G)
1> c(big, [native]).
{ok,big}
2> big:bang(4).
2.80000e-5

both emulators are vanilla compiles, i.e. no tweaking. Both machines
run debian linux. Both machines have 32 bit AMD x86 CPUs.

Matthias
unknown
2006-04-03 19:57:17 UTC
Permalink
In my case the host has 2 CPUs (seen as 4 in hyper-threaded mode), which
support 64-bit architecture, yet 32-bit Linux RedHat ES 4.0 is installed.

I did remove, plain vanilla compile and reinstall Erlang, and still get
the same core dump. I am second guessing my prior statement about this
test running successfully on another host with the same hardware. Right
now I don't have access to that machine, but will get a chance to verify
that later on this week.

$ cat /proc/cpuinfo | egrep "processor|model\ name"
processor : 0
model name : Intel(R) Xeon(TM) CPU 3.60GHz
processor : 1
model name : Intel(R) Xeon(TM) CPU 3.60GHz
processor : 2
model name : Intel(R) Xeon(TM) CPU 3.60GHz
processor : 3
model name : Intel(R) Xeon(TM) CPU 3.60GHz

The box has 4G RAM.
cat /proc/meminfo
MemTotal: 4149312 kB
MemFree: 1815708 kB
Buffers: 393516 kB
Cached: 1660744 kB
...

Serge
Post by unknown
Ops... Sorry, this test case was taken from Rickard Green's post
Oh, ok. I assumed 'big' was something you'd written. Anyway, I ran it
Linux antilipe 2.6.12.1 #3 Wed Jan 11 16:25:06 CET 2006 i686 GNU/Linux
tmp >erl
Erlang (BEAM) emulator version 5.4.13 [source] [hipe]
Eshell V5.4.13 (abort with ^G)
1> c(big, [native]).
{ok,big}
2> big:bang(4).
2.30000e-5
and
Linux cors 2.4.27 #5 Tue Feb 15 15:15:03 CET 2005 i686 GNU/Linux
matthias:/tmp$ erl
Erlang (BEAM) emulator version 5.4.13 [source] [hipe]
Eshell V5.4.13 (abort with ^G)
1> c(big, [native]).
{ok,big}
2> big:bang(4).
2.80000e-5
both emulators are vanilla compiles, i.e. no tweaking. Both machines
run debian linux. Both machines have 32 bit AMD x86 CPUs.
Matthias
--
Serge Aleynikov
R&D Telecom, IDT Corp.
Tel: (973) 438-3436
Fax: (973) 438-1464
serge
unknown
2006-04-05 13:19:33 UTC
Permalink
Post by unknown
Ops... Sorry, this test case was taken from Rickard Green's post on
profiling P11B smp scheduling support. I wanted to run it on multi-cpu
host, and installed R10B-10 and P11B releases with and without hipe.
...
Post by unknown
Erlang (BEAM) emulator version 5.4.13 [source] [hipe] [threads:0]
Eshell V5.4.13 (abort with ^G)
1> c(big, [native]).
{ok,big}
2> big:bang(4).
Segmentation fault (core dumped)
...
Post by unknown
(gdb) bt
#0 0x08aae41c in ?? ()
#1 0x080f0f63 in x86_call_to_native () at hipe/hipe_x86_glue.S:42
#2 0x00000000 in ?? ()
(gdb)
...
ENTER_FROM_C
/* get argument registers */
LOAD_ARG_REGS
/* call the target */
NSP_CALL(*P_NCALLEE(P)) <-- Failing here
I'm not sure what this call does, but maybe Mikael can give a clue.
This is the entry point for BEAM calling a native-compiled function.
NSP_CALL() currently expands to a plain "call" instruction; it's a macro so
we can experiment with and measure other ways of performing calls and returns.

I'm unable to reproduce your problem here. The closest machine we
have to yours is a dual HT P4 Xeon of the older 32-bit only type,
running FC4 user-space on a custom 2.6.9-34 RHEL4 kernel, and things
just work. Your test case also works on an Athlon64 running the same
FC4/RHEL4 combo in pure 64-bit mode.

It would help if you could run beam from gdb (easiest is to attach to
it, otherwise you have to set up several environment variables), and
print the exact location of the program counter at the crash, list the
surrounding assembler code, print the registers, and also the print the
contents of "P" (print *p in a C frame, print *(Process*)$ebp ought to
do the same in assembler mode).

/Mikael
unknown
2006-04-05 17:54:14 UTC
Permalink
Mikael,

Here's a bunch of info you requested. Let's continue this discussion
outside of the mailing list's scope, and just post the resolution
when/if it's available.

Regards,

Serge

(gdb) where
#0 0x08aae424 in ?? ()
#1 0x080f0f63 in x86_call_to_native () at hipe/hipe_x86_glue.S:42
#2 0x00000000 in ?? ()

Current instruction:
(gdb) p/x $pc
$2 = 0x8aae424

Next instruction:
(gdb) x/i $pc
0x8aae424: lea 0xffffff78(%esp),%ebx

(gdb) list
42 NSP_CALL(*P_NCALLEE(P))
43 /*
44 * We export this return address so that hipe_mode_switch() can
discover
45 * when native code tailcalls emulated code.
46 *
47 * This is where native code returns to emulated code.
48 */
49 nbif_return:
50 movl %eax, P_ARG0(P) # save retval
51 movl $HIPE_MODE_SWITCH_RES_RETURN, %eax

(gdb) disas 0x08aae424
No function contains specified address.

(gdb) disas 0x080f0f63
Dump of assembler code for function nbif_return:
0x080f0f63 <nbif_return+0>: mov %eax,0x4c(%ebp)
0x080f0f66 <nbif_return+3>: mov $0x5,%eax
End of assembler dump.

(gdb) info registers
eax 0x4f 79
ecx 0xb7d568e9 -1210750743
edx 0x578b 22411
ebx 0xb7eca674 -1209227660
esp 0x8ab059c 0x8ab059c
ebp 0xb7eca674 0xb7eca674
esi 0xb7d52980 -1210766976
edi 0x18 24
eip 0x8aae424 0x8aae424
eflags 0x10286 66182
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51

(gdb) print *(Process*)$ebp
$1 = {htop = 0xb7d52980, stop = 0xb7d52a30, heap = 0xb7d52108, hend =
0xb7d52a90, heap_sz = 610, min_heap_size = 233, hipe = {
nsp = 0x8ab05a0, nstack = 0x8ab03a0, nstend = 0x8ab05a0, ncallee =
0x8aae424, closure = 11, nstgraylim = 0x0,
nstblacklim = 0x0, ngra = 0, ncsp = 0xbffff46c, narity = 0}, arity
= 0, arg_reg = 0xb7eca6c0, max_arg_reg = 6, def_arg_reg = {
79, 22411, 3084216553, 135076450, 0, 1000}, cp = 0x81b18b8, i =
0x0, catches = 0, fcalls = 600, status = 3, rstatus = 0,
rcount = 0, id = 499, prio = 2, skipped = 0, reds = 968,
error_handler = 6859, tracer_proc = 4294967291, group_leader = 387,
flags = 0, fvalue = 4294967291, freason = 848, ftrace = 4294967291,
dist_entry = 0x0, tm = {next = 0x0, slot = 0, count = 0,
active = 0, timeout = 0, cancel = 0, arg = 0x0}, next = 0x0, reg =
0x0, nlinks = 0xb7ecacdc, monitors = 0x0, msg = {
first = 0x0, last = 0xb7eca750, save = 0xb7eca750, len = 0},
bif_timers = 0x0, dictionary = 0x0, debug_dictionary = 0x0,
ct = 0x0, seq_trace_clock = 0, seq_trace_lastcnt = 0, seq_trace_token
= 4294967291, initial = {6731, 22411, 2}, current = 0x0,
parent = 403, started = 1144245940, high_water = 0xb7d52604, old_hend
= 0xb7d513c8, old_htop = 0xb7d50aa0,
old_heap = 0xb7d50a40, gen_gcs = 4, max_gen_gcs = 65535, off_heap =
{mso = 0x0, funs = 0xb7d52944, externals = 0x0,
overhead = 0}, mbuf = 0x0, mbuf_sz = 0, arith_heap = 0x0,
arith_avail = 0}
Post by unknown
Post by unknown
Ops... Sorry, this test case was taken from Rickard Green's post on
profiling P11B smp scheduling support. I wanted to run it on multi-cpu
host, and installed R10B-10 and P11B releases with and without hipe.
...
Post by unknown
Erlang (BEAM) emulator version 5.4.13 [source] [hipe] [threads:0]
Eshell V5.4.13 (abort with ^G)
1> c(big, [native]).
{ok,big}
2> big:bang(4).
Segmentation fault (core dumped)
...
Post by unknown
(gdb) bt
#0 0x08aae41c in ?? ()
#1 0x080f0f63 in x86_call_to_native () at hipe/hipe_x86_glue.S:42
#2 0x00000000 in ?? ()
(gdb)
...
ENTER_FROM_C
/* get argument registers */
LOAD_ARG_REGS
/* call the target */
NSP_CALL(*P_NCALLEE(P)) <-- Failing here
I'm not sure what this call does, but maybe Mikael can give a clue.
This is the entry point for BEAM calling a native-compiled function.
NSP_CALL() currently expands to a plain "call" instruction; it's a macro so
we can experiment with and measure other ways of performing calls and returns.
I'm unable to reproduce your problem here. The closest machine we
have to yours is a dual HT P4 Xeon of the older 32-bit only type,
running FC4 user-space on a custom 2.6.9-34 RHEL4 kernel, and things
just work. Your test case also works on an Athlon64 running the same
FC4/RHEL4 combo in pure 64-bit mode.
It would help if you could run beam from gdb (easiest is to attach to
it, otherwise you have to set up several environment variables), and
print the exact location of the program counter at the crash, list the
surrounding assembler code, print the registers, and also the print the
contents of "P" (print *p in a C frame, print *(Process*)$ebp ought to
do the same in assembler mode).
/Mikael
--
Serge Aleynikov
R&D Telecom, IDT Corp.
Tel: (973) 438-3436
Fax: (973) 438-1464
serge
unknown
2006-04-06 19:44:07 UTC
Permalink
Post by unknown
Mikael,
Here's a bunch of info you requested. Let's continue this discussion
outside of the mailing list's scope, and just post the resolution
when/if it's available.
[gdb session omitted]

Problem solved. According to the gdb session everything looked OK,
yet the code couldn't be executed. It turns out that with the fairly
new processor model Serge is using, the Linux kernel makes normal
data memory non-executable by default. We've seen this long ago on
AMD64 machines with 64-bit kernels, but never before on machines with
32-bit kernels. The solution is to adapt the specially written AMD64
code memory allocation routines for use on x86 as well.

The patch below solves this problem. It's been checked in on the R11
development branch and should be applied to R10B-10 as well.

/Mikael

--- otp-0330/erts/emulator/hipe/hipe_amd64.h.~1~ 2005-12-15 12:29:52.000000000 +0100
+++ otp-0330/erts/emulator/hipe/hipe_amd64.h 2006-04-06 17:46:19.000000000 +0200
@@ -14,10 +14,6 @@

#define hipe_arch_name am_amd64

-/* for hipe_bifs_enter_code_2 */
-extern void *hipe_alloc_code(Uint nrbytes, Eterm callees, Eterm *trampolines, Process *p);
-#define HIPE_ALLOC_CODE(n,c,t,p) hipe_alloc_code((n),(c),(t),(p))
-
extern const Uint sse2_fnegate_mask[];

#endif /* HIPE_AMD64_H */
--- otp-0330/erts/emulator/hipe/hipe_x86.c.~1~ 2005-12-15 12:29:53.000000000 +0100
+++ otp-0330/erts/emulator/hipe/hipe_x86.c 2006-04-06 19:23:59.000000000 +0200
@@ -50,6 +50,114 @@
return 0;
}

+/*
+ * Memory allocator for executable code.
+ *
+ * This is required on x86 because some combinations
+ * of Linux kernels and CPU generations default to
+ * non-executable memory mappings, causing ordinary
+ * malloc() memory to be non-executable.
+ */
+static unsigned int code_bytes;
+static char *code_next;
+
+#if 0 /* change to non-zero to get allocation statistics at exit() */
+static unsigned int total_mapped, nr_joins, nr_splits, total_alloc, nr_allocs, nr_large, total_lost;
+static unsigned int atexit_done;
+
+static void alloc_code_stats(void)
+{
+ printf("\r\nalloc_code_stats: %u bytes mapped, %u joins, %u splits, %u bytes allocated, %u average alloc, %u large allocs, %u bytes lost\r\n",
+ total_mapped, nr_joins, nr_splits, total_alloc, nr_allocs ? total_alloc/nr_allocs : 0, nr_large, total_lost);
+}
+
+static void atexit_alloc_code_stats(void)
+{
+ if (!atexit_done) {
+ atexit_done = 1;
+ (void)atexit(alloc_code_stats);
+ }
+}
+
+#define ALLOC_CODE_STATS(X) do{X;}while(0)
+#else
+#define ALLOC_CODE_STATS(X) do{}while(0)
+#endif
+
+static void morecore(unsigned int alloc_bytes)
+{
+ unsigned int map_bytes;
+ char *map_hint, *map_start;
+
+ /* Page-align the amount to allocate. */
+ map_bytes = (alloc_bytes + 4095) & ~4095;
+
+ /* Round up small allocations. */
+ if (map_bytes < 1024*1024)
+ map_bytes = 1024*1024;
+ else
+ ALLOC_CODE_STATS(++nr_large);
+
+ /* Create a new memory mapping, ensuring it is executable
+ and in the low 2GB of the address space. Also attempt
+ to make it adjacent to the previous mapping. */
+ map_hint = code_next + code_bytes;
+ if ((unsigned long)map_hint & 4095)
+ abort();
+ map_start = mmap(map_hint, map_bytes,
+ PROT_EXEC|PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANONYMOUS
+#ifdef __x86_64__
+ |MAP_32BIT
+#endif
+ ,
+ -1, 0);
+ if (map_start == MAP_FAILED) {
+ perror("mmap");
+ abort();
+ }
+ ALLOC_CODE_STATS(total_mapped += map_bytes);
+
+ /* Merge adjacent mappings, so the trailing portion of the previous
+ mapping isn't lost. In practice this is quite successful. */
+ if (map_start == map_hint) {
+ ALLOC_CODE_STATS(++nr_joins);
+ code_bytes += map_bytes;
+ } else {
+ ALLOC_CODE_STATS(++nr_splits);
+ ALLOC_CODE_STATS(total_lost += code_bytes);
+ code_next = map_start;
+ code_bytes = map_bytes;
+ }
+
+ ALLOC_CODE_STATS(atexit_alloc_code_stats());
+}
+
+static void *alloc_code(unsigned int alloc_bytes)
+{
+ void *res;
+
+ /* Align function entries. */
+ alloc_bytes = (alloc_bytes + 3) & ~3;
+
+ if (code_bytes < alloc_bytes)
+ morecore(alloc_bytes);
+ ALLOC_CODE_STATS(++nr_allocs);
+ ALLOC_CODE_STATS(total_alloc += alloc_bytes);
+ res = code_next;
+ code_next += alloc_bytes;
+ code_bytes -= alloc_bytes;
+ return res;
+}
+
+void *hipe_alloc_code(Uint nrbytes, Eterm callees, Eterm *trampolines, Process *p)
+{
+ if (is_not_nil(callees))
+ return NULL;
+ *trampolines = NIL;
+ return alloc_code(nrbytes);
+}
+
/* called from hipe_bif0.c:hipe_bifs_make_native_stub_2()
and hipe_bif0.c:hipe_make_stub() */
void *hipe_make_native_stub(void *beamAddress, unsigned int beamArity)
@@ -76,7 +184,7 @@
16 + /* 16 when both offsets are 8-bit */
(P_BEAM_IP >= 128 ? 3 : 0) +
(P_ARITY >= 128 ? 3 : 0);
- codep = code = erts_alloc(ERTS_ALC_T_HIPE, codeSize);
+ codep = code = alloc_code(codeSize);

/* movl $beamAddress, P_BEAM_IP(%ebp); 3 or 6 bytes, plus 4 */
codep[0] = 0xc7;
--- otp-0330/erts/emulator/hipe/hipe_x86.h.~1~ 2005-12-15 12:29:53.000000000 +0100
+++ otp-0330/erts/emulator/hipe/hipe_x86.h 2006-04-06 17:45:48.000000000 +0200
@@ -39,4 +39,8 @@
extern void nbif_inc_stack_0(void);
extern void nbif_handle_fp_exception(void);

+/* for hipe_bifs_enter_code_2 */
+extern void *hipe_alloc_code(Uint nrbytes, Eterm callees, Eterm *trampolines, Process *p);
+#define HIPE_ALLOC_CODE(n,c,t,p) hipe_alloc_code((n),(c),(t),(p))
+
#endif /* HIPE_X86_H */
unknown
2006-04-06 19:53:57 UTC
Permalink
Mikael,

Thanks for the quick turnaround!

Serge
Post by unknown
Post by unknown
Mikael,
Here's a bunch of info you requested. Let's continue this discussion
outside of the mailing list's scope, and just post the resolution
when/if it's available.
[gdb session omitted]
Problem solved. According to the gdb session everything looked OK,
yet the code couldn't be executed. It turns out that with the fairly
new processor model Serge is using, the Linux kernel makes normal
data memory non-executable by default. We've seen this long ago on
AMD64 machines with 64-bit kernels, but never before on machines with
32-bit kernels. The solution is to adapt the specially written AMD64
code memory allocation routines for use on x86 as well.
The patch below solves this problem. It's been checked in on the R11
development branch and should be applied to R10B-10 as well.
/Mikael
--- otp-0330/erts/emulator/hipe/hipe_amd64.h.~1~ 2005-12-15 12:29:52.000000000 +0100
+++ otp-0330/erts/emulator/hipe/hipe_amd64.h 2006-04-06 17:46:19.000000000 +0200
@@ -14,10 +14,6 @@
#define hipe_arch_name am_amd64
-/* for hipe_bifs_enter_code_2 */
-extern void *hipe_alloc_code(Uint nrbytes, Eterm callees, Eterm *trampolines, Process *p);
-#define HIPE_ALLOC_CODE(n,c,t,p) hipe_alloc_code((n),(c),(t),(p))
-
extern const Uint sse2_fnegate_mask[];
#endif /* HIPE_AMD64_H */
--- otp-0330/erts/emulator/hipe/hipe_x86.c.~1~ 2005-12-15 12:29:53.000000000 +0100
+++ otp-0330/erts/emulator/hipe/hipe_x86.c 2006-04-06 19:23:59.000000000 +0200
@@ -50,6 +50,114 @@
return 0;
}
+/*
+ * Memory allocator for executable code.
+ *
+ * This is required on x86 because some combinations
+ * of Linux kernels and CPU generations default to
+ * non-executable memory mappings, causing ordinary
+ * malloc() memory to be non-executable.
+ */
+static unsigned int code_bytes;
+static char *code_next;
+
+#if 0 /* change to non-zero to get allocation statistics at exit() */
+static unsigned int total_mapped, nr_joins, nr_splits, total_alloc, nr_allocs, nr_large, total_lost;
+static unsigned int atexit_done;
+
+static void alloc_code_stats(void)
+{
+ printf("\r\nalloc_code_stats: %u bytes mapped, %u joins, %u splits, %u bytes allocated, %u average alloc, %u large allocs, %u bytes lost\r\n",
+ total_mapped, nr_joins, nr_splits, total_alloc, nr_allocs ? total_alloc/nr_allocs : 0, nr_large, total_lost);
+}
+
+static void atexit_alloc_code_stats(void)
+{
+ if (!atexit_done) {
+ atexit_done = 1;
+ (void)atexit(alloc_code_stats);
+ }
+}
+
+#define ALLOC_CODE_STATS(X) do{X;}while(0)
+#else
+#define ALLOC_CODE_STATS(X) do{}while(0)
+#endif
+
+static void morecore(unsigned int alloc_bytes)
+{
+ unsigned int map_bytes;
+ char *map_hint, *map_start;
+
+ /* Page-align the amount to allocate. */
+ map_bytes = (alloc_bytes + 4095) & ~4095;
+
+ /* Round up small allocations. */
+ if (map_bytes < 1024*1024)
+ map_bytes = 1024*1024;
+ else
+ ALLOC_CODE_STATS(++nr_large);
+
+ /* Create a new memory mapping, ensuring it is executable
+ and in the low 2GB of the address space. Also attempt
+ to make it adjacent to the previous mapping. */
+ map_hint = code_next + code_bytes;
+ if ((unsigned long)map_hint & 4095)
+ abort();
+ map_start = mmap(map_hint, map_bytes,
+ PROT_EXEC|PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANONYMOUS
+#ifdef __x86_64__
+ |MAP_32BIT
+#endif
+ ,
+ -1, 0);
+ if (map_start == MAP_FAILED) {
+ perror("mmap");
+ abort();
+ }
+ ALLOC_CODE_STATS(total_mapped += map_bytes);
+
+ /* Merge adjacent mappings, so the trailing portion of the previous
+ mapping isn't lost. In practice this is quite successful. */
+ if (map_start == map_hint) {
+ ALLOC_CODE_STATS(++nr_joins);
+ code_bytes += map_bytes;
+ } else {
+ ALLOC_CODE_STATS(++nr_splits);
+ ALLOC_CODE_STATS(total_lost += code_bytes);
+ code_next = map_start;
+ code_bytes = map_bytes;
+ }
+
+ ALLOC_CODE_STATS(atexit_alloc_code_stats());
+}
+
+static void *alloc_code(unsigned int alloc_bytes)
+{
+ void *res;
+
+ /* Align function entries. */
+ alloc_bytes = (alloc_bytes + 3) & ~3;
+
+ if (code_bytes < alloc_bytes)
+ morecore(alloc_bytes);
+ ALLOC_CODE_STATS(++nr_allocs);
+ ALLOC_CODE_STATS(total_alloc += alloc_bytes);
+ res = code_next;
+ code_next += alloc_bytes;
+ code_bytes -= alloc_bytes;
+ return res;
+}
+
+void *hipe_alloc_code(Uint nrbytes, Eterm callees, Eterm *trampolines, Process *p)
+{
+ if (is_not_nil(callees))
+ return NULL;
+ *trampolines = NIL;
+ return alloc_code(nrbytes);
+}
+
/* called from hipe_bif0.c:hipe_bifs_make_native_stub_2()
and hipe_bif0.c:hipe_make_stub() */
void *hipe_make_native_stub(void *beamAddress, unsigned int beamArity)
@@ -76,7 +184,7 @@
16 + /* 16 when both offsets are 8-bit */
(P_BEAM_IP >= 128 ? 3 : 0) +
(P_ARITY >= 128 ? 3 : 0);
- codep = code = erts_alloc(ERTS_ALC_T_HIPE, codeSize);
+ codep = code = alloc_code(codeSize);
/* movl $beamAddress, P_BEAM_IP(%ebp); 3 or 6 bytes, plus 4 */
codep[0] = 0xc7;
--- otp-0330/erts/emulator/hipe/hipe_x86.h.~1~ 2005-12-15 12:29:53.000000000 +0100
+++ otp-0330/erts/emulator/hipe/hipe_x86.h 2006-04-06 17:45:48.000000000 +0200
@@ -39,4 +39,8 @@
extern void nbif_inc_stack_0(void);
extern void nbif_handle_fp_exception(void);
+/* for hipe_bifs_enter_code_2 */
+extern void *hipe_alloc_code(Uint nrbytes, Eterm callees, Eterm *trampolines, Process *p);
+#define HIPE_ALLOC_CODE(n,c,t,p) hipe_alloc_code((n),(c),(t),(p))
+
#endif /* HIPE_X86_H */
--
Serge Aleynikov
R&D Telecom, IDT Corp.
Tel: (973) 438-3436
Fax: (973) 438-1464
serge
unknown
2006-05-05 13:36:45 UTC
Permalink
Mikael,

When I applied this patch to FC5 Linux 64-bit OS, Erlang compiled fine,
however when I did the same on a 32-bit Linux FC5 OS, the make process
failed with the errors shown below.

Serge

gcc -g -O3 -I/home/serge/Projects/Distrs/R10B-10/erts/i686-pc-linux-gnu
-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -DHYBRID
-DHAVE_CONFIG_H -Wall -Wstrict-prototypes -Wmissing-prototypes
-D_THREAD_SAFE -D_REENTRANT -DUSE_THREADS -Ibeam -Isys/unix
-Isys/common -Ii686-pc-linux-gnu -Ii686-pc-linux-gnu/hybrid -Izlib
-Ihipe -I../include/internal -I../include/internal/i686-pc-linux-gnu -c
hipe/hipe_x86.c -o
/home/serge/Projects/Distrs/R10B-10/erts/obj.hybrid.beam/i686-pc-linux-gnu/hipe_x86.o
hipe/hipe_x86.c: In function 'morecore':
hipe/hipe_x86.c:107: warning: implicit declaration of function 'mmap'
hipe/hipe_x86.c:108: error: 'PROT_EXEC' undeclared (first use in this
function)
hipe/hipe_x86.c:108: error: (Each undeclared identifier is reported only
once
hipe/hipe_x86.c:108: error: for each function it appears in.)
hipe/hipe_x86.c:108: error: 'PROT_READ' undeclared (first use in this
function)
hipe/hipe_x86.c:108: error: 'PROT_WRITE' undeclared (first use in this
function)
hipe/hipe_x86.c:109: error: 'MAP_PRIVATE' undeclared (first use in this
function)
hipe/hipe_x86.c:109: error: 'MAP_ANONYMOUS' undeclared (first use in
this function)
hipe/hipe_x86.c:114: warning: assignment makes pointer from integer
without a cast
hipe/hipe_x86.c:115: error: 'MAP_FAILED' undeclared (first use in this
function)
make[3]: ***
[/home/serge/Projects/Distrs/R10B-10/erts/obj.hybrid.beam/i686-pc-linux-gnu/hipe_x86.o]
Error 1
make[3]: Leaving directory
`/home/serge/Projects/Distrs/R10B-10/erts/emulator'
make[2]: *** [hybrid] Error 2
make[2]: Leaving directory
`/home/serge/Projects/Distrs/R10B-10/erts/emulator'
make[1]: *** [hybrid] Error 2
make[1]: Leaving directory `/home/serge/Projects/Distrs/R10B-10/erts'
make: *** [emulator] Error 2
Post by unknown
Post by unknown
Mikael,
Here's a bunch of info you requested. Let's continue this discussion
outside of the mailing list's scope, and just post the resolution
when/if it's available.
[gdb session omitted]
Problem solved. According to the gdb session everything looked OK,
yet the code couldn't be executed. It turns out that with the fairly
new processor model Serge is using, the Linux kernel makes normal
data memory non-executable by default. We've seen this long ago on
AMD64 machines with 64-bit kernels, but never before on machines with
32-bit kernels. The solution is to adapt the specially written AMD64
code memory allocation routines for use on x86 as well.
The patch below solves this problem. It's been checked in on the R11
development branch and should be applied to R10B-10 as well.
/Mikael
--- otp-0330/erts/emulator/hipe/hipe_amd64.h.~1~ 2005-12-15 12:29:52.000000000 +0100
+++ otp-0330/erts/emulator/hipe/hipe_amd64.h 2006-04-06 17:46:19.000000000 +0200
@@ -14,10 +14,6 @@
#define hipe_arch_name am_amd64
-/* for hipe_bifs_enter_code_2 */
-extern void *hipe_alloc_code(Uint nrbytes, Eterm callees, Eterm *trampolines, Process *p);
-#define HIPE_ALLOC_CODE(n,c,t,p) hipe_alloc_code((n),(c),(t),(p))
-
extern const Uint sse2_fnegate_mask[];
#endif /* HIPE_AMD64_H */
--- otp-0330/erts/emulator/hipe/hipe_x86.c.~1~ 2005-12-15 12:29:53.000000000 +0100
+++ otp-0330/erts/emulator/hipe/hipe_x86.c 2006-04-06 19:23:59.000000000 +0200
@@ -50,6 +50,114 @@
return 0;
}
+/*
+ * Memory allocator for executable code.
+ *
+ * This is required on x86 because some combinations
+ * of Linux kernels and CPU generations default to
+ * non-executable memory mappings, causing ordinary
+ * malloc() memory to be non-executable.
+ */
+static unsigned int code_bytes;
+static char *code_next;
+
+#if 0 /* change to non-zero to get allocation statistics at exit() */
+static unsigned int total_mapped, nr_joins, nr_splits, total_alloc, nr_allocs, nr_large, total_lost;
+static unsigned int atexit_done;
+
+static void alloc_code_stats(void)
+{
+ printf("\r\nalloc_code_stats: %u bytes mapped, %u joins, %u splits, %u bytes allocated, %u average alloc, %u large allocs, %u bytes lost\r\n",
+ total_mapped, nr_joins, nr_splits, total_alloc, nr_allocs ? total_alloc/nr_allocs : 0, nr_large, total_lost);
+}
+
+static void atexit_alloc_code_stats(void)
+{
+ if (!atexit_done) {
+ atexit_done = 1;
+ (void)atexit(alloc_code_stats);
+ }
+}
+
+#define ALLOC_CODE_STATS(X) do{X;}while(0)
+#else
+#define ALLOC_CODE_STATS(X) do{}while(0)
+#endif
+
+static void morecore(unsigned int alloc_bytes)
+{
+ unsigned int map_bytes;
+ char *map_hint, *map_start;
+
+ /* Page-align the amount to allocate. */
+ map_bytes = (alloc_bytes + 4095) & ~4095;
+
+ /* Round up small allocations. */
+ if (map_bytes < 1024*1024)
+ map_bytes = 1024*1024;
+ else
+ ALLOC_CODE_STATS(++nr_large);
+
+ /* Create a new memory mapping, ensuring it is executable
+ and in the low 2GB of the address space. Also attempt
+ to make it adjacent to the previous mapping. */
+ map_hint = code_next + code_bytes;
+ if ((unsigned long)map_hint & 4095)
+ abort();
+ map_start = mmap(map_hint, map_bytes,
+ PROT_EXEC|PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANONYMOUS
+#ifdef __x86_64__
+ |MAP_32BIT
+#endif
+ ,
+ -1, 0);
+ if (map_start == MAP_FAILED) {
+ perror("mmap");
+ abort();
+ }
+ ALLOC_CODE_STATS(total_mapped += map_bytes);
+
+ /* Merge adjacent mappings, so the trailing portion of the previous
+ mapping isn't lost. In practice this is quite successful. */
+ if (map_start == map_hint) {
+ ALLOC_CODE_STATS(++nr_joins);
+ code_bytes += map_bytes;
+ } else {
+ ALLOC_CODE_STATS(++nr_splits);
+ ALLOC_CODE_STATS(total_lost += code_bytes);
+ code_next = map_start;
+ code_bytes = map_bytes;
+ }
+
+ ALLOC_CODE_STATS(atexit_alloc_code_stats());
+}
+
+static void *alloc_code(unsigned int alloc_bytes)
+{
+ void *res;
+
+ /* Align function entries. */
+ alloc_bytes = (alloc_bytes + 3) & ~3;
+
+ if (code_bytes < alloc_bytes)
+ morecore(alloc_bytes);
+ ALLOC_CODE_STATS(++nr_allocs);
+ ALLOC_CODE_STATS(total_alloc += alloc_bytes);
+ res = code_next;
+ code_next += alloc_bytes;
+ code_bytes -= alloc_bytes;
+ return res;
+}
+
+void *hipe_alloc_code(Uint nrbytes, Eterm callees, Eterm *trampolines, Process *p)
+{
+ if (is_not_nil(callees))
+ return NULL;
+ *trampolines = NIL;
+ return alloc_code(nrbytes);
+}
+
/* called from hipe_bif0.c:hipe_bifs_make_native_stub_2()
and hipe_bif0.c:hipe_make_stub() */
void *hipe_make_native_stub(void *beamAddress, unsigned int beamArity)
@@ -76,7 +184,7 @@
16 + /* 16 when both offsets are 8-bit */
(P_BEAM_IP >= 128 ? 3 : 0) +
(P_ARITY >= 128 ? 3 : 0);
- codep = code = erts_alloc(ERTS_ALC_T_HIPE, codeSize);
+ codep = code = alloc_code(codeSize);
/* movl $beamAddress, P_BEAM_IP(%ebp); 3 or 6 bytes, plus 4 */
codep[0] = 0xc7;
--- otp-0330/erts/emulator/hipe/hipe_x86.h.~1~ 2005-12-15 12:29:53.000000000 +0100
+++ otp-0330/erts/emulator/hipe/hipe_x86.h 2006-04-06 17:45:48.000000000 +0200
@@ -39,4 +39,8 @@
extern void nbif_inc_stack_0(void);
extern void nbif_handle_fp_exception(void);
+/* for hipe_bifs_enter_code_2 */
+extern void *hipe_alloc_code(Uint nrbytes, Eterm callees, Eterm *trampolines, Process *p);
+#define HIPE_ALLOC_CODE(n,c,t,p) hipe_alloc_code((n),(c),(t),(p))
+
#endif /* HIPE_X86_H */
--
Serge Aleynikov
R&D Telecom, IDT Corp.
Tel: (973) 438-3436
Fax: (973) 438-1464
serge
unknown
2006-04-06 04:48:52 UTC
Permalink
Post by unknown
Post by unknown
Ops... Sorry, this test case was taken from Rickard Green's post on
profiling P11B smp scheduling support. I wanted to run it on multi-cpu
host, and installed R10B-10 and P11B releases with and without hipe.
...
Post by unknown
Erlang (BEAM) emulator version 5.4.13 [source] [hipe] [threads:0]
Eshell V5.4.13 (abort with ^G)
1> c(big, [native]).
{ok,big}
2> big:bang(4).
Segmentation fault (core dumped)
...
Post by unknown
(gdb) bt
#0 0x08aae41c in ?? ()
#1 0x080f0f63 in x86_call_to_native () at hipe/hipe_x86_glue.S:42
#2 0x00000000 in ?? ()
(gdb)
...
ENTER_FROM_C
/* get argument registers */
LOAD_ARG_REGS
/* call the target */
NSP_CALL(*P_NCALLEE(P)) <-- Failing here
I'm not sure what this call does, but maybe Mikael can give a clue.
This is the entry point for BEAM calling a native-compiled function.
NSP_CALL() currently expands to a plain "call" instruction; it's a macro so
we can experiment with and measure other ways of performing calls and returns.
I'm unable to reproduce your problem here. The closest machine we
have to yours is a dual HT P4 Xeon of the older 32-bit only type,
running FC4 user-space on a custom 2.6.9-34 RHEL4 kernel, and things
just work. Your test case also works on an Athlon64 running the same
FC4/RHEL4 combo in pure 64-bit mode.
It would help if you could run beam from gdb (easiest is to attach to
it, otherwise you have to set up several environment variables), and
print the exact location of the program counter at the crash, list the
surrounding assembler code, print the registers, and also the print the
contents of "P" (print *p in a C frame, print *(Process*)$ebp ought to
do the same in assembler mode).
/Mikael
Hello,
For information, on FC5 with kernel 2.6.16-1.2080_FC5.i686

Erlang (BEAM) emulator version 5.4.13 [source] [hipe] [threads:0]

Eshell V5.4.13 (abort with ^G)
1> c(big).
{ok,big}
2> big:bang(4).
3.20000e-5
3> c(big, [native]).
{ok,big}
4> big:bang(4).
Erreur de segmentation

And i got segmentation fault with ALL native compilations.
But with a switch to kernel 2.6.15-1.2054_FC5.i686, native compilation
work.

Regards.
unknown
2006-04-06 08:54:16 UTC
Permalink
Post by unknown
For information, on FC5 with kernel 2.6.16-1.2080_FC5.i686
Erlang (BEAM) emulator version 5.4.13 [source] [hipe] [threads:0]
Eshell V5.4.13 (abort with ^G)
1> c(big).
{ok,big}
2> big:bang(4).
3.20000e-5
3> c(big, [native]).
{ok,big}
4> big:bang(4).
Erreur de segmentation
And i got segmentation fault with ALL native compilations.
But with a switch to kernel 2.6.15-1.2054_FC5.i686, native compilation
work.
Does this Erlang system have the glibc-2.4 fix applied? (See below.)

Does the problem go away if you build without thread support? There was
a bug in the sigaltstack() setup, but I've only seen the ill effects on
the SMP system, never on R10B. The fact that a 2.6.16-based kernel breaks
while a pre-2.6.16 kernel works hints strongly at the sigaltstack() bug.

/Mikael

--- otp-0317/erts/emulator/hipe/hipe_x86_signal.c.~1~ 2005-10-21 14:02:57.000000000 +0200
+++ otp-0317/erts/emulator/hipe/hipe_x86_signal.c 2006-03-27 12:30:08.000000000 +0200
@@ -27,7 +27,7 @@
#include <stdlib.h>
#include "hipe_signal.h"

-#if __GLIBC__ == 2 && __GLIBC_MINOR__ == 3
+#if __GLIBC__ == 2 && (__GLIBC_MINOR__ == 3 || __GLIBC_MINOR__ == 4)
/* See comment below for glibc 2.2. */
#ifndef __USE_GNU
#define __USE_GNU /* to un-hide RTLD_NEXT */
unknown
2006-04-07 04:58:51 UTC
Permalink
Post by unknown
Post by unknown
Mikael,
Here's a bunch of info you requested. Let's continue this
discussion
Post by unknown
Post by unknown
outside of the mailing list's scope, and just post the resolution
when/if it's available.
[gdb session omitted]
......................
......................
Hello,

Now, native compilation works with applied patches.

Many thanks.
unknown
2006-05-06 16:19:06 UTC
Permalink
Your explanation makes perfect sense indeed, and in search for the
answer, I did find that HAVE_MMAP was *not* set by configure on this
machine.

What is see is that if I try to do:

$ rm -fr otp_src_R10B-10
$ tar xzf otp_src_R10B-10.tar.gz
$ cd otp_src_R10B-10
$ ./configure --enable-threads | grep mmap
checking for working mmap... yes

so mmap gets defined fine. However, if I run autoconf-2.13 in erts,
mmap doesn't get found:

$ rm -fr otp_src_R10B-10
$ tar xzf otp_src_R10B-10.tar.gz
$ cd otp_src_R10B-10/erts
$ autoconf-2.13
$ cd ..
$ ./configure --enable-threads | grep mmap
checking for working mmap... no

However, when autoconf is being used instead of autoconf-2.13 in the
case above, mmap gets found all right.

Anyone has any idea why?

Serge
Post by unknown
When I applied this patch to FC5 Linux 64-bit OS, Erlang compiled fine,
however when I did the same on a 32-bit Linux FC5 OS, the make process
failed with the errors shown below.
Serge
gcc -g -O3 -I/home/serge/Projects/Distrs/R10B-10/erts/i686-pc-linux-gnu
-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -DHYBRID
-DHAVE_CONFIG_H -Wall -Wstrict-prototypes -Wmissing-prototypes
-D_THREAD_SAFE -D_REENTRANT -DUSE_THREADS -Ibeam -Isys/unix
-Isys/common -Ii686-pc-linux-gnu -Ii686-pc-linux-gnu/hybrid -Izlib
-Ihipe -I../include/internal -I../include/internal/i686-pc-linux-gnu -c
hipe/hipe_x86.c -o
/home/serge/Projects/Distrs/R10B-10/erts/obj.hybrid.beam/i686-pc-linux-gnu/hipe_x86.o
hipe/hipe_x86.c:107: warning: implicit declaration of function 'mmap'
hipe/hipe_x86.c:108: error: 'PROT_EXEC' undeclared (first use in this
function)
hipe/hipe_x86.c:108: error: (Each undeclared identifier is reported only
once
hipe/hipe_x86.c:108: error: for each function it appears in.)
hipe/hipe_x86.c:108: error: 'PROT_READ' undeclared (first use in this
function)
hipe/hipe_x86.c:108: error: 'PROT_WRITE' undeclared (first use in this
function)
hipe/hipe_x86.c:109: error: 'MAP_PRIVATE' undeclared (first use in this
function)
hipe/hipe_x86.c:109: error: 'MAP_ANONYMOUS' undeclared (first use in
this function)
hipe/hipe_x86.c:114: warning: assignment makes pointer from integer
without a cast
hipe/hipe_x86.c:115: error: 'MAP_FAILED' undeclared (first use in this
function)
This means that, for some reason, an #include of <sys/mman.h> was lost.
This shouldn't happen: hipe_x86.c includes global.h, which includes
sys.h, which includes erl_unix_sys.h (unless one of __WIN32__/VXWORKS/_OSE_
is defined), which includes <sys/mman.h> unless erts/configure decided
that HAVE_MMAP should be 0, which shouldn't be possible on FC5.
I've built R10B-10 on an FC5 box (i686, 100% vanilla, no updates),
and no problems occurred. I can't explain why things don't work for you,
but simply adding "#include <sys/mman.h>" at the end of the
#include directives in hipe_x86.c ought to work.
/Mikael
unknown
2006-05-06 17:21:06 UTC
Permalink
Post by unknown
Your explanation makes perfect sense indeed, and in search for the
answer, I did find that HAVE_MMAP was *not* set by configure on this
machine.
$ rm -fr otp_src_R10B-10
$ tar xzf otp_src_R10B-10.tar.gz
$ cd otp_src_R10B-10
$ ./configure --enable-threads | grep mmap
checking for working mmap... yes
That's what users are supposed to do, and it clearly works.
Indeed.
My guess is that the OTP team's autoconf-2.13 is different somehow
from the autoconf-2.13 .rpm in Fedora.
Why are you regenerating erts/configure? Do you have local
modifications to erts/configure.in?
We implemented SCTP support for OTP in a form of a patch that requires
to modify erts/configure.in.
If you add the "#include <sys/mman.h>" to hipe_x86.c as I
described, does the system then build OK, or do other things
still break because of the missing HAVE_MMAP?
Yes, it does get compiled fine in that case.

Serge
unknown
2006-05-05 23:48:05 UTC
Permalink
Post by unknown
When I applied this patch to FC5 Linux 64-bit OS, Erlang compiled fine,
however when I did the same on a 32-bit Linux FC5 OS, the make process
failed with the errors shown below.
Serge
gcc -g -O3 -I/home/serge/Projects/Distrs/R10B-10/erts/i686-pc-linux-gnu
-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -DHYBRID
-DHAVE_CONFIG_H -Wall -Wstrict-prototypes -Wmissing-prototypes
-D_THREAD_SAFE -D_REENTRANT -DUSE_THREADS -Ibeam -Isys/unix
-Isys/common -Ii686-pc-linux-gnu -Ii686-pc-linux-gnu/hybrid -Izlib
-Ihipe -I../include/internal -I../include/internal/i686-pc-linux-gnu -c
hipe/hipe_x86.c -o
/home/serge/Projects/Distrs/R10B-10/erts/obj.hybrid.beam/i686-pc-linux-gnu/hipe_x86.o
hipe/hipe_x86.c:107: warning: implicit declaration of function 'mmap'
hipe/hipe_x86.c:108: error: 'PROT_EXEC' undeclared (first use in this
function)
hipe/hipe_x86.c:108: error: (Each undeclared identifier is reported only
once
hipe/hipe_x86.c:108: error: for each function it appears in.)
hipe/hipe_x86.c:108: error: 'PROT_READ' undeclared (first use in this
function)
hipe/hipe_x86.c:108: error: 'PROT_WRITE' undeclared (first use in this
function)
hipe/hipe_x86.c:109: error: 'MAP_PRIVATE' undeclared (first use in this
function)
hipe/hipe_x86.c:109: error: 'MAP_ANONYMOUS' undeclared (first use in
this function)
hipe/hipe_x86.c:114: warning: assignment makes pointer from integer
without a cast
hipe/hipe_x86.c:115: error: 'MAP_FAILED' undeclared (first use in this
function)
This means that, for some reason, an #include of <sys/mman.h> was lost.
This shouldn't happen: hipe_x86.c includes global.h, which includes
sys.h, which includes erl_unix_sys.h (unless one of __WIN32__/VXWORKS/_OSE_
is defined), which includes <sys/mman.h> unless erts/configure decided
that HAVE_MMAP should be 0, which shouldn't be possible on FC5.

I've built R10B-10 on an FC5 box (i686, 100% vanilla, no updates),
and no problems occurred. I can't explain why things don't work for you,
but simply adding "#include <sys/mman.h>" at the end of the
#include directives in hipe_x86.c ought to work.

/Mikael
unknown
2006-05-06 17:13:35 UTC
Permalink
Post by unknown
Your explanation makes perfect sense indeed, and in search for the
answer, I did find that HAVE_MMAP was *not* set by configure on this
machine.
$ rm -fr otp_src_R10B-10
$ tar xzf otp_src_R10B-10.tar.gz
$ cd otp_src_R10B-10
$ ./configure --enable-threads | grep mmap
checking for working mmap... yes
That's what users are supposed to do, and it clearly works.
Post by unknown
so mmap gets defined fine. However, if I run autoconf-2.13 in erts,
$ rm -fr otp_src_R10B-10
$ tar xzf otp_src_R10B-10.tar.gz
$ cd otp_src_R10B-10/erts
$ autoconf-2.13
$ cd ..
$ ./configure --enable-threads | grep mmap
checking for working mmap... no
However, when autoconf is being used instead of autoconf-2.13 in the
case above, mmap gets found all right.
Anyone has any idea why?
My guess is that the OTP team's autoconf-2.13 is different somehow
from the autoconf-2.13 .rpm in Fedora.

Why are you regenerating erts/configure? Do you have local
modifications to erts/configure.in?

If you add the "#include <sys/mman.h>" to hipe_x86.c as I
described, does the system then build OK, or do other things
still break because of the missing HAVE_MMAP?

/Mikael
unknown
2006-05-07 22:01:16 UTC
Permalink
Post by unknown
If you add the "#include <sys/mman.h>" to hipe_x86.c as I
described, does the system then build OK, or do other things
still break because of the missing HAVE_MMAP?
Yes, it does get compiled fine in that case.
Here's a patch (for devel branch but applies to R10B as well)
that adds explicit #include <sys/mman.h> to those HiPE runtime
system files that use mmap(). This should be unnecessary since
erl_unix_sys.h includes <sys/mman.h> if erts/configure found
mmap(), but as Serge has shown that is not completely reliable.

/Mikael

--- otp-0501/erts/emulator/hipe/hipe_amd64.c.~1~ 2005-12-15 12:29:52.000000000 +0100
+++ otp-0501/erts/emulator/hipe/hipe_amd64.c 2006-05-07 21:03:48.000000000 +0200
@@ -4,6 +4,7 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+#include <sys/mman.h>
#include "global.h"
#include "error.h"
#include "bif.h"
--- otp-0501/erts/emulator/hipe/hipe_arm.c.~1~ 2005-12-16 01:45:29.000000000 +0100
+++ otp-0501/erts/emulator/hipe/hipe_arm.c 2006-05-07 21:03:48.000000000 +0200
@@ -4,6 +4,7 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+#include <sys/mman.h>
#include "global.h"

#include "hipe_arch.h"
--- otp-0501/erts/emulator/hipe/hipe_ppc.c.~1~ 2005-12-15 18:14:43.000000000 +0100
+++ otp-0501/erts/emulator/hipe/hipe_ppc.c 2006-05-07 21:03:48.000000000 +0200
@@ -4,6 +4,7 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+#include <sys/mman.h>
#include "global.h"

#include "hipe_arch.h"
--- otp-0501/erts/emulator/hipe/hipe_x86.c.~1~ 2006-04-06 21:08:41.000000000 +0200
+++ otp-0501/erts/emulator/hipe/hipe_x86.c 2006-05-07 21:03:48.000000000 +0200
@@ -4,6 +4,7 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+#include <sys/mman.h>
#include "global.h"

#include "hipe_arch.h"
unknown
2006-05-09 07:31:38 UTC
Permalink
Post by unknown
Post by unknown
If you add the "#include <sys/mman.h>" to hipe_x86.c as I
described, does the system then build OK, or do other things
still break because of the missing HAVE_MMAP?
Yes, it does get compiled fine in that case.
Here's a patch (for devel branch but applies to R10B as well)
that adds explicit #include <sys/mman.h> to those HiPE runtime
system files that use mmap(). This should be unnecessary since
erl_unix_sys.h includes <sys/mman.h> if erts/configure found
mmap(), but as Serge has shown that is not completely reliable.
Sorry, scratch that and use this patch instead. The previous patch
worked fine on Linux and Solaris, but broke an #include ordering
constraint on Mac OSX (10.3.9). This new patch fixes that.

/Mikael

--- otp-0501/erts/emulator/hipe/hipe_amd64.c.~1~ 2005-12-15 12:29:52.000000000 +0100
+++ otp-0501/erts/emulator/hipe/hipe_amd64.c 2006-05-09 09:21:20.000000000 +0200
@@ -5,6 +5,7 @@
#include "config.h"
#endif
#include "global.h"
+#include <sys/mman.h>
#include "error.h"
#include "bif.h"
#include "big.h" /* term_to_Sint() */
--- otp-0501/erts/emulator/hipe/hipe_arm.c.~1~ 2005-12-16 01:45:29.000000000 +0100
+++ otp-0501/erts/emulator/hipe/hipe_arm.c 2006-05-09 09:21:20.000000000 +0200
@@ -5,6 +5,7 @@
#include "config.h"
#endif
#include "global.h"
+#include <sys/mman.h>

#include "hipe_arch.h"
#include "hipe_native_bif.h" /* nbif_callemu() */
--- otp-0501/erts/emulator/hipe/hipe_ppc.c.~1~ 2005-12-15 18:14:43.000000000 +0100
+++ otp-0501/erts/emulator/hipe/hipe_ppc.c 2006-05-09 09:21:20.000000000 +0200
@@ -5,6 +5,7 @@
#include "config.h"
#endif
#include "global.h"
+#include <sys/mman.h>

#include "hipe_arch.h"
#include "hipe_native_bif.h" /* nbif_callemu() */
--- otp-0501/erts/emulator/hipe/hipe_x86.c.~1~ 2006-04-06 21:08:41.000000000 +0200
+++ otp-0501/erts/emulator/hipe/hipe_x86.c 2006-05-09 09:21:20.000000000 +0200
@@ -5,6 +5,7 @@
#include "config.h"
#endif
#include "global.h"
+#include <sys/mman.h>

#include "hipe_arch.h"
#include "hipe_native_bif.h" /* nbif_callemu() */

Loading...