Re: [Myrinet] kernel panic initiated by gm driver version 1.5.2
Susan Blackford <[email protected]>
| Newsgroups | gmane.network.myrinet.general |
|---|---|
| Organization | Myricom, Inc. |
| Message-ID | <0206251205290A.00536@idefix> |
Hi, On Tuesday 25 June 2002 08:53 am, you wrote: > When running a user program the system went into a kernel > hung state after issuing the following messages: > > kernel: GM: PANIC: > libgm/_gm_assertion_failed.c:27:_gm_assertion_failed():kernel > kernel: GM: drivers/linux/gm/gm_arch_fork.c:126: failed assertion: > "!pmd_none (*src_pmd) && !pmd_bad (*src_pmd)". > kernel: Kernel panic: gm_arch_abort() called > > Our system is running Linux kernel version 2.4.17. This is a bug related to the recently introduced fork() support in gm-1.5.2, and unfortunately passed through our tests. This bug affects only the driver, so you should apply the patch, recompile the driver, and reload the gm module. This patch will be available on the Linux Download page, and will be included in the next release of GM. Attached is the patch and the analysis from the developer. (cd <gmsrcdir>;patch -p1 < .../fork4.diff) When creating a new mapping that just perfectly fits the hole between two previous mapping, Linux merge the two old areas and the new one into one into just one chunk, and although the original right area is removed (its range now being part of the big reunited chunk), Linux never calls the ->close method on it, which causes the GM driver to lose track of the areas on which it has registered hooks. The reason Linux does not care to call the close method is because areas susceptible to be merged are anonymous and normally never have a "->close" method anyway, but this is no longer the case with the GM driver where we use the vm_area open and close method for fork() support, (and they are actually generally called in all other creation/destruction cases), there is just this weird corner case that I hadn't noticed before :-(. The fix is to make any vm area with registered page "non-mergeable" (see can_vma_merge in include/linux/mm.h), by attaching them to a pseudo file. Using the vm_file attribute. We have the shmem_file_setup function starting with 2.4.4 that can be used to creates the dumb file used for this purpose (and there is no problem for earlier 2.4 kernels where no vm merge is ever done, 2.2 kernels always call the vm_area->open/close method before creating/destroying them). We increase the dependence on Linux internals when we have to insert/deinsert the vm areas from the mapping list attached to the pseudo-inode of the pseudo-file, but all 2.4 kernels(included redhat or other variant) seems to use exactly the same simple linked list for this purpose. We apologize for the inconvenience. Please confirm with us that this patch solves your problem. Susan -- ------------------------------------------ Susan Blackford Member of Technical Staff Myricom Inc. ------------------------------------------
fork4.diff
(text/plain, 35.8 KB)
Index: gm/configure
diff -u gm/configure:1.279 gm/configure:1.279.14.1
--- gm/configure:1.279 Tue May 28 16:27:20 2002
+++ gm/configure Fri Jun 21 05:57:14 2002
@@ -1914,8 +1914,48 @@
fi
done
+ for ac_hdr in asm/rmap.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1922: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1927 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1932: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
cat > conftest.$ac_ext <<EOF
-#line 1919 "configure"
+#line 1959 "configure"
#include "confdefs.h"
#include <linux/autoconf.h>
#ifdef CONFIG_SMP
@@ -1930,7 +1970,7 @@
rm -f conftest*
cat > conftest.$ac_ext <<EOF
-#line 1934 "configure"
+#line 1974 "configure"
#include "confdefs.h"
#include <linux/autoconf.h>
#ifdef CONFIG_MODVERSIONS
@@ -2893,7 +2933,7 @@
echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
-echo "configure:2897: checking whether ${MAKE-make} sets \${MAKE}" >&5
+echo "configure:2937: checking whether ${MAKE-make} sets \${MAKE}" >&5
set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -2923,7 +2963,7 @@
# Extract the first word of "ar", so it can be a program name with args.
set dummy ar; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2927: checking for $ac_word" >&5
+echo "configure:2967: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_AR'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -2959,7 +2999,7 @@
# Extract the first word of "basename", so it can be a program name with args.
set dummy basename; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2963: checking for $ac_word" >&5
+echo "configure:3003: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_BASENAME'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -2995,7 +3035,7 @@
# Extract the first word of "cat", so it can be a program name with args.
set dummy cat; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2999: checking for $ac_word" >&5
+echo "configure:3039: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_CAT'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3031,7 +3071,7 @@
# Extract the first word of "chmod", so it can be a program name with args.
set dummy chmod; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3035: checking for $ac_word" >&5
+echo "configure:3075: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_CHMOD'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3067,7 +3107,7 @@
# Extract the first word of "ctags", so it can be a program name with args.
set dummy ctags; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3071: checking for $ac_word" >&5
+echo "configure:3111: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_CTAGS'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3103,7 +3143,7 @@
# Extract the first word of "distill", so it can be a program name with args.
set dummy distill; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3107: checking for $ac_word" >&5
+echo "configure:3147: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_DISTILL'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3139,7 +3179,7 @@
# Extract the first word of "dvips", so it can be a program name with args.
set dummy dvips; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3143: checking for $ac_word" >&5
+echo "configure:3183: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_DVIPS'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3175,7 +3215,7 @@
# Extract the first word of "echo", so it can be a program name with args.
set dummy echo; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3179: checking for $ac_word" >&5
+echo "configure:3219: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_ECHO'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3211,7 +3251,7 @@
# Extract the first word of "etags", so it can be a program name with args.
set dummy etags; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3215: checking for $ac_word" >&5
+echo "configure:3255: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_ETAGS'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3247,7 +3287,7 @@
# Extract the first word of "gendat", so it can be a program name with args.
set dummy gendat; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3251: checking for $ac_word" >&5
+echo "configure:3291: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_GENDAT'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3283,7 +3323,7 @@
# Extract the first word of "gs", so it can be a program name with args.
set dummy gs; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3287: checking for $ac_word" >&5
+echo "configure:3327: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_GS'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3328,7 +3368,7 @@
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:3332: checking for a BSD compatible install" >&5
+echo "configure:3372: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -3383,7 +3423,7 @@
# Extract the first word of "install-info", so it can be a program name with args.
set dummy install-info; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3387: checking for $ac_word" >&5
+echo "configure:3427: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_INSTALL_INFO'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3419,7 +3459,7 @@
# Extract the first word of "lanai-gcc", so it can be a program name with args.
set dummy lanai-gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3423: checking for $ac_word" >&5
+echo "configure:3463: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_LANAI_GCC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3455,7 +3495,7 @@
# Extract the first word of "lanai-ar", so it can be a program name with args.
set dummy lanai-ar; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3459: checking for $ac_word" >&5
+echo "configure:3499: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_LANAI_AR'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3491,7 +3531,7 @@
# Extract the first word of "ld", so it can be a program name with args.
set dummy ld; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3495: checking for $ac_word" >&5
+echo "configure:3535: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_LD'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3525,7 +3565,7 @@
fi
echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
-echo "configure:3529: checking whether ln -s works" >&5
+echo "configure:3569: checking whether ln -s works" >&5
if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3548,7 +3588,7 @@
# Extract the first word of "makeinfo", so it can be a program name with args.
set dummy makeinfo; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3552: checking for $ac_word" >&5
+echo "configure:3592: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_MAKEINFO'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3584,7 +3624,7 @@
# Extract the first word of "psrev", so it can be a program name with args.
set dummy psrev; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3588: checking for $ac_word" >&5
+echo "configure:3628: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_PSREV'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3620,7 +3660,7 @@
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3624: checking for $ac_word" >&5
+echo "configure:3664: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3650,7 +3690,7 @@
# Extract the first word of "strip", so it can be a program name with args.
set dummy strip; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3654: checking for $ac_word" >&5
+echo "configure:3694: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_STRIP'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3686,7 +3726,7 @@
# Extract the first word of "texi2dvi", so it can be a program name with args.
set dummy texi2dvi; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3690: checking for $ac_word" >&5
+echo "configure:3730: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_TEXI2DVI'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3722,7 +3762,7 @@
# Extract the first word of "texi2html", so it can be a program name with args.
set dummy texi2html; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3726: checking for $ac_word" >&5
+echo "configure:3766: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_TEXI2HTML'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3786,12 +3826,12 @@
echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:3790: checking for ANSI C header files" >&5
+echo "configure:3830: checking for ANSI C header files" >&5
if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3795 "configure"
+#line 3835 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <stdarg.h>
@@ -3799,7 +3839,7 @@
#include <float.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:3803: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:3843: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -3816,7 +3856,7 @@
if test $ac_cv_header_stdc = yes; then
# SunOS 4.x string.h does not declare mem*, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 3820 "configure"
+#line 3860 "configure"
#include "confdefs.h"
#include <string.h>
EOF
@@ -3834,7 +3874,7 @@
if test $ac_cv_header_stdc = yes; then
# ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 3838 "configure"
+#line 3878 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
@@ -3855,7 +3895,7 @@
:
else
cat > conftest.$ac_ext <<EOF
-#line 3859 "configure"
+#line 3899 "configure"
#include "confdefs.h"
#include <ctype.h>
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -3866,7 +3906,7 @@
exit (0); }
EOF
-if { (eval echo configure:3870: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:3910: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
:
else
@@ -3893,17 +3933,17 @@
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:3897: checking for $ac_hdr" >&5
+echo "configure:3937: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3902 "configure"
+#line 3942 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:3907: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:3947: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -3931,12 +3971,12 @@
echo $ac_n "checking for working const""... $ac_c" 1>&6
-echo "configure:3935: checking for working const" >&5
+echo "configure:3975: checking for working const" >&5
if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3940 "configure"
+#line 3980 "configure"
#include "confdefs.h"
int main() {
@@ -3985,7 +4025,7 @@
; return 0; }
EOF
-if { (eval echo configure:3989: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4029: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_const=yes
else
@@ -4006,21 +4046,21 @@
fi
echo $ac_n "checking for inline""... $ac_c" 1>&6
-echo "configure:4010: checking for inline" >&5
+echo "configure:4050: checking for inline" >&5
if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_cv_c_inline=no
for ac_kw in inline __inline__ __inline; do
cat > conftest.$ac_ext <<EOF
-#line 4017 "configure"
+#line 4057 "configure"
#include "confdefs.h"
int main() {
} int $ac_kw foo() {
; return 0; }
EOF
-if { (eval echo configure:4024: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4064: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_inline=$ac_kw; break
else
@@ -4046,12 +4086,12 @@
esac
echo $ac_n "checking for off_t""... $ac_c" 1>&6
-echo "configure:4050: checking for off_t" >&5
+echo "configure:4090: checking for off_t" >&5
if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4055 "configure"
+#line 4095 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
@@ -4079,12 +4119,12 @@
fi
echo $ac_n "checking for size_t""... $ac_c" 1>&6
-echo "configure:4083: checking for size_t" >&5
+echo "configure:4123: checking for size_t" >&5
if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4088 "configure"
+#line 4128 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
@@ -4112,12 +4152,12 @@
fi
echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6
-echo "configure:4116: checking for uid_t in sys/types.h" >&5
+echo "configure:4156: checking for uid_t in sys/types.h" >&5
if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4121 "configure"
+#line 4161 "configure"
#include "confdefs.h"
#include <sys/types.h>
EOF
@@ -4148,13 +4188,13 @@
if test $ac_cv_prog_gcc = yes; then
echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6
-echo "configure:4152: checking whether ${CC-cc} needs -traditional" >&5
+echo "configure:4192: checking whether ${CC-cc} needs -traditional" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_pattern="Autoconf.*'x'"
cat > conftest.$ac_ext <<EOF
-#line 4158 "configure"
+#line 4198 "configure"
#include "confdefs.h"
#include <sgtty.h>
Autoconf TIOCGETP
@@ -4172,7 +4212,7 @@
if test $ac_cv_prog_gcc_traditional = no; then
cat > conftest.$ac_ext <<EOF
-#line 4176 "configure"
+#line 4216 "configure"
#include "confdefs.h"
#include <termio.h>
Autoconf TCGETA
@@ -4197,17 +4237,17 @@
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:4201: checking for $ac_hdr" >&5
+echo "configure:4241: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4206 "configure"
+#line 4246 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:4211: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:4251: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -4236,12 +4276,12 @@
for ac_func in getpagesize
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:4240: checking for $ac_func" >&5
+echo "configure:4280: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4245 "configure"
+#line 4285 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -4264,7 +4304,7 @@
; return 0; }
EOF
-if { (eval echo configure:4268: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4308: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -4289,7 +4329,7 @@
done
echo $ac_n "checking for working mmap""... $ac_c" 1>&6
-echo "configure:4293: checking for working mmap" >&5
+echo "configure:4333: checking for working mmap" >&5
if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -4297,7 +4337,7 @@
ac_cv_func_mmap_fixed_mapped=no
else
cat > conftest.$ac_ext <<EOF
-#line 4301 "configure"
+#line 4341 "configure"
#include "confdefs.h"
/* Thanks to Mike Haertel and Jim Avera for this test.
@@ -4440,7 +4480,7 @@
}
EOF
-if { (eval echo configure:4444: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:4484: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_func_mmap_fixed_mapped=yes
else
@@ -4463,12 +4503,12 @@
fi
echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
-echo "configure:4467: checking return type of signal handlers" >&5
+echo "configure:4507: checking return type of signal handlers" >&5
if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4472 "configure"
+#line 4512 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <signal.h>
@@ -4485,7 +4525,7 @@
int i;
; return 0; }
EOF
-if { (eval echo configure:4489: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4529: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_type_signal=void
else
@@ -4506,12 +4546,12 @@
for ac_func in memalign atexit on_exit
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:4510: checking for $ac_func" >&5
+echo "configure:4550: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4515 "configure"
+#line 4555 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -4534,7 +4574,7 @@
; return 0; }
EOF
-if { (eval echo configure:4538: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4578: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -4564,7 +4604,7 @@
# Checks for libraries.
# Replace `main' with a function in -lgcc:
echo $ac_n "checking for main in -lgcc""... $ac_c" 1>&6
-echo "configure:4568: checking for main in -lgcc" >&5
+echo "configure:4608: checking for main in -lgcc" >&5
ac_lib_var=`echo gcc'_'main | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -4572,14 +4612,14 @@
ac_save_LIBS="$LIBS"
LIBS="-lgcc $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 4576 "configure"
+#line 4616 "configure"
#include "confdefs.h"
int main() {
main()
; return 0; }
EOF
-if { (eval echo configure:4583: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4623: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -4607,14 +4647,14 @@
fi
echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
-echo "configure:4611: checking whether byte ordering is bigendian" >&5
+echo "configure:4651: checking whether byte ordering is bigendian" >&5
if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_cv_c_bigendian=unknown
# See if sys/param.h defines the BYTE_ORDER macro.
cat > conftest.$ac_ext <<EOF
-#line 4618 "configure"
+#line 4658 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/param.h>
@@ -4625,11 +4665,11 @@
#endif
; return 0; }
EOF
-if { (eval echo configure:4629: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4669: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
# It does; now see whether it defined to BIG_ENDIAN or not.
cat > conftest.$ac_ext <<EOF
-#line 4633 "configure"
+#line 4673 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/param.h>
@@ -4640,7 +4680,7 @@
#endif
; return 0; }
EOF
-if { (eval echo configure:4644: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4684: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_bigendian=yes
else
@@ -4660,7 +4700,7 @@
{ echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
else
cat > conftest.$ac_ext <<EOF
-#line 4664 "configure"
+#line 4704 "configure"
#include "confdefs.h"
main () {
/* Are we little or big endian? From Harbison&Steele. */
@@ -4673,7 +4713,7 @@
exit (u.c[sizeof (long) - 1] == 1);
}
EOF
-if { (eval echo configure:4677: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:4717: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_c_bigendian=no
else
Index: gm/configure.in
diff -u gm/configure.in:1.271 gm/configure.in:1.271.32.1
--- gm/configure.in:1.271 Tue Apr 9 08:18:24 2002
+++ gm/configure.in Fri Jun 21 05:57:18 2002
@@ -441,6 +441,7 @@
oldflags="$CPPFLAGS"
CPPFLAGS="-nostdinc -I$LINUX_KERSRC/include"
AC_CHECK_HEADERS(linux/compile.h)
+ AC_CHECK_HEADERS(asm/rmap.h)
AC_EGREP_CPP(config_smp,
[#include <linux/autoconf.h>
#ifdef CONFIG_SMP
Index: gm/drivers/linux/gm/gm_arch.c
diff -u gm/drivers/linux/gm/gm_arch.c:1.291 gm/drivers/linux/gm/gm_arch.c:1.291.8.3
--- gm/drivers/linux/gm/gm_arch.c:1.291 Tue Jun 4 06:41:27 2002
+++ gm/drivers/linux/gm/gm_arch.c Tue Jun 25 05:35:09 2002
@@ -57,6 +57,7 @@
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/module.h>
+#include <linux/file.h>
#if GM_SUPPORT_PCI
#include <linux/pci.h>
@@ -258,6 +259,12 @@
gm_hash_hash_ptr,
0, 0,
3, 0);
+#if LINUX_VERSION_CODE >= VERSION_CODE(2,4,4)
+ /* shmem_file_setup is only available after 2.4.4
+ as vm merging is not done between 2.4.0 and 2.4.9
+ that is not a problem */
+ ps->arch.file = shmem_file_setup ("gm-reg-file", 0);
+#endif
return ps->arch.ops_hash ? GM_SUCCESS : GM_FAILURE;
}
@@ -271,6 +278,13 @@
GM_PARAMETER_MAY_BE_UNUSED (ps);
gm_assert(ps->arch.ops_count == 0);
gm_destroy_hash(ps->arch.ops_hash);
+#if LINUX_XX >= 24
+ if (ps->arch.file)
+ {
+ gm_assert (atomic_read (&ps->arch.file->f_count) == 1);
+ fput (ps->arch.file);
+ }
+#endif
return;
}
@@ -3150,6 +3164,11 @@
init_MUTEX (&gm_linux_open_mutex);
spin_lock_init (&gm_linux_intr_lock);
+ gm_linux_get_user_pages = (int (*)())gm_linux_symbol("get_user_pages");
+ if (!gm_linux_get_user_pages)
+ {
+ GM_INFO (("kernel does not export get_user_pages\n"));
+ }
#if GM_SUPPORT_PCI
if (pci_module_init (&gm_driver) != 0)
{
Index: gm/drivers/linux/gm/gm_arch_def.h
diff -u gm/drivers/linux/gm/gm_arch_def.h:1.34 gm/drivers/linux/gm/gm_arch_def.h:1.34.18.1
--- gm/drivers/linux/gm/gm_arch_def.h:1.34 Thu May 23 10:22:31 2002
+++ gm/drivers/linux/gm/gm_arch_def.h Fri Jun 21 05:57:20 2002
@@ -239,4 +239,8 @@
extern spinlock_t gm_linux_intr_lock;
extern struct gm_hash *gm_linux_pfn_hash;
+int (*gm_linux_get_user_pages)(struct task_struct *tsk, struct mm_struct *mm,
+ unsigned long start, int len, int write, int force,
+ struct page **pages, struct vm_area_struct **vmas);
+
#endif /* _gm_arch_def_h_ */
Index: gm/drivers/linux/gm/gm_arch_fork.c
diff -u gm/drivers/linux/gm/gm_arch_fork.c:1.6 gm/drivers/linux/gm/gm_arch_fork.c:1.6.8.2
--- gm/drivers/linux/gm/gm_arch_fork.c:1.6 Tue Jun 4 06:41:28 2002
+++ gm/drivers/linux/gm/gm_arch_fork.c Fri Jun 21 05:57:20 2002
@@ -59,35 +59,61 @@
atomic_read (&old_page->count)));
return;
}
- new_page = alloc_page (GFP_HIGHUSER);
-
- /* copy new_page */
- new = kmap (new_page);
- old = kmap (old_page);
+ if (!gm_linux_get_user_pages)
+ {
+#ifdef HAVE_ASM_RMAP_H
+ GM_WARN (("fork() not supported on this kernel when GM ports are open"));
+ return;
+#endif
+ new_page = alloc_page (GFP_HIGHUSER);
+
+ /* copy new_page */
+ new = kmap (new_page);
+ old = kmap (old_page);
#if GM_CPU_ia64 || GM_CPU_powerpc
- memcpy(new,old,PAGE_SIZE);
+ memcpy(new,old,PAGE_SIZE);
#else
- copy_user_page (new, old, addr_base);
+ copy_user_page (new, old, addr_base);
#endif
- kunmap (old_page);
- kunmap (new_page);
+ kunmap (old_page);
+ kunmap (new_page);
#if !GM_CPU_powerpc
- flush_page_to_ram (old_page);
- flush_page_to_ram (new_page);
+ flush_page_to_ram (old_page);
+ flush_page_to_ram (new_page);
#endif
- flush_cache_page (vma, addr_base);
- set_pte (dst_pte,
- pte_mkwrite (pte_mkdirty (mk_pte (new_page, vma->vm_page_prot))));
- page_cache_release (old_page); /* remove child reference */
- /* put again original page in rw mode */
- set_pte (src_pte, pte_mkwrite (*src_pte));
+ flush_cache_page (vma, addr_base);
+ set_pte (dst_pte,
+ pte_mkwrite (pte_mkdirty (mk_pte (new_page, vma->vm_page_prot))));
+ page_cache_release (old_page); /* remove child reference */
+ /* put again original page in rw mode */
+ set_pte (src_pte, pte_mkwrite (*src_pte));
#if LINUX_XX >= 24 && !GM_CPU_ia64 && !GM_CPU_powerpc
- /* we do not need this as we are in fork, we only modified the child tlb which has never
- been active and there will be a flush_tlb_page before that happens,
- we are in dup_mmap in the parent and there is a flush_tlb_mm at the end
- of this function */
- flush_tlb_page (vma, addr_base);
+ /* we do not need this as we are in fork, we only modified the
+ child tlb which has never been active and there will be a
+ flush_tlb_page before that happens, we are in dup_mmap in the
+ parent and there is a flush_tlb_mm at the end of this
+ function */
+ flush_tlb_page (vma, addr_base);
#endif
+ }
+ else /* fonction get_user_pages available */
+ {
+ int res;
+ vma->vm_mm->mmap_cache = vma;
+ res = (*gm_linux_get_user_pages) (current,vma->vm_mm, addr_base, 1,
+ 1, 0, &new_page, NULL);
+ gm_always_assert (res == 1);
+ gm_always_assert (new_page != old_page);
+ gm_always_assert (pte_present (*src_pte) && pte_present (*dst_pte) &&
+ !pte_write (*src_pte) && pte_write (*dst_pte) &&
+ l24_pte_page (*dst_pte) == new_page &&
+ l24_pte_page (*src_pte) == old_page);
+ /* page count should be: 1 in parent, 1 in child, 1 in page_hash */
+ gm_always_assert (atomic_read (&old_page->count) == 2);
+ gm_always_assert (atomic_read (&new_page->count) == 2);
+ page_cache_release (new_page);
+ set_pte (src_pte, pte_mkwrite (*src_pte));
+ }
}
void
@@ -109,8 +135,11 @@
unsigned long pmd_end = pmd_off + vma->vm_end - addr;
pmd_t *src_pmd, *dst_pmd;
/* check valid pgd entries */
- gm_always_assert (!pgd_none (*src_pgd) && !pgd_bad (*src_pgd));
- gm_always_assert (!pgd_none (*dst_pgd) && !pgd_bad (*dst_pgd));
+ if (pgd_none (*src_pgd) || pgd_bad (*src_pgd) ||
+ pgd_none (*dst_pgd) || pgd_bad (*dst_pgd))
+ {
+ goto continue_pgd_loop;
+ }
src_pmd = pmd_offset (src_pgd, pmd_off);
dst_pmd = pmd_offset (dst_pgd, pmd_off);
if (pmd_end > PGDIR_SIZE)
@@ -123,8 +152,11 @@
unsigned long pte_end = pte_off + pmd_end - pmd_off;
pte_t *src_pte, *dst_pte;
/* check valid pmd entries */
- gm_always_assert (!pmd_none (*src_pmd) && !pmd_bad (*src_pmd));
- gm_always_assert (!pmd_none (*dst_pmd) && !pmd_bad (*dst_pmd));
+ if (pmd_none (*src_pmd) || pmd_bad (*src_pmd) ||
+ pmd_none (*dst_pmd) || pmd_bad (*dst_pmd))
+ {
+ goto continue_pmd_loop;
+ }
src_pte = pte_offset (src_pmd, pte_off);
dst_pte = pte_offset (dst_pmd, pte_off);
if (pte_end > PMD_SIZE)
@@ -150,10 +182,12 @@
}
}
} /* end pte loop */
+ continue_pmd_loop:
pmd_off = (pmd_off + PMD_SIZE) & PMD_MASK;
src_pmd++;
dst_pmd++;
} /* end pmd loop */
+ continue_pgd_loop:
addr = (addr + PGDIR_SIZE) & PGDIR_MASK;
src_pgd++;
dst_pgd++;
Index: gm/drivers/linux/gm/gm_arch_linux.h
diff -u gm/drivers/linux/gm/gm_arch_linux.h:1.11 gm/drivers/linux/gm/gm_arch_linux.h:1.11.16.1
--- gm/drivers/linux/gm/gm_arch_linux.h:1.11 Fri May 31 16:34:56 2002
+++ gm/drivers/linux/gm/gm_arch_linux.h Tue Jun 25 05:05:49 2002
@@ -137,8 +137,8 @@
return 1;
}
-
-
+#define up_mmap_sem(a)
+#define down_mmap_sem(a)
#elif LINUX_24
Index: gm/drivers/linux/gm/gm_arch_types.h
diff -u gm/drivers/linux/gm/gm_arch_types.h:1.49 gm/drivers/linux/gm/gm_arch_types.h:1.49.8.1
--- gm/drivers/linux/gm/gm_arch_types.h:1.49 Tue Jun 4 06:41:28 2002
+++ gm/drivers/linux/gm/gm_arch_types.h Tue Jun 25 05:05:49 2002
@@ -113,6 +113,7 @@
struct gm_hash *ops_hash;
int ops_count;
struct mm_struct *mm;
+ struct file * file;
}
gm_arch_port_info_t;
Index: gm/drivers/linux/gm/gm_arch_vmops.c
diff -u gm/drivers/linux/gm/gm_arch_vmops.c:1.4 gm/drivers/linux/gm/gm_arch_vmops.c:1.4.8.1
--- gm/drivers/linux/gm/gm_arch_vmops.c:1.4 Tue Jun 4 06:41:28 2002
+++ gm/drivers/linux/gm/gm_arch_vmops.c Tue Jun 25 05:05:49 2002
@@ -7,8 +7,27 @@
#include "gm_internal.h"
#include <linux/mm.h>
+#include <linux/file.h>
static void
+gm_linux_detach_file (struct vm_area_struct *vma)
+{
+#if LINUX_XX >= 24
+ gm_linux_vm_ops_t *ops = (gm_linux_vm_ops_t *) vma->vm_ops;
+ struct gm_port_state * ps = ops->gm.ps;
+ if (vma->vm_file && vma->vm_file == ps->arch.file)
+ {
+ vma->vm_file = 0;
+ gm_assert (atomic_read (&ps->arch.file->f_count) > 1);
+ if (vma->vm_next_share)
+ vma->vm_next_share->vm_pprev_share = vma->vm_pprev_share;
+ *vma->vm_pprev_share = vma->vm_next_share;
+ fput(ps->arch.file);
+ }
+#endif
+}
+
+static void
gm_linux_vm_open (struct vm_area_struct *vma)
{
gm_linux_vm_ops_t *ops = (gm_linux_vm_ops_t *) vma->vm_ops;
@@ -19,6 +38,9 @@
{
/* ok we are doing a fork, I do believe this is the only case
where the equality does not hold in open */
+ /* the kernel has duplicated the vma
+ and increased the reference of vm_file before calling us */
+ gm_linux_detach_file (vma);
vma->vm_ops = ops->gm.ori;
gm_linux_fork (vma);
}
@@ -37,6 +59,7 @@
gm_assert (ops->gm.refcount > 0);
ops->gm.refcount -= 1;
+ gm_linux_detach_file (vma);
vma->vm_ops = ops->gm.ori;
if (!ops->gm.refcount)
{
@@ -145,6 +168,27 @@
return GM_OUT_OF_MEMORY;
vma->vm_ops = &ops->wrap;
ops->gm.refcount += 1;
+#if LINUX_XX >= 24
+ /* prevent Linux anonymous vma merge operations (see can_vma_merge
+ in linux/mm.h)which unfortunately do not guarantee to call open
+ and close method on the object, to do that we transform the
+ anonymous vm_area into a file object */
+ if (!vma->vm_file && ps->arch.file)
+ {
+ struct inode * inode = ps->arch.file->f_dentry->d_inode;
+ struct address_space * mapping = inode->i_mapping;
+ struct vm_area_struct **head = &mapping->i_mmap;
+
+ get_file (ps->arch.file);
+ vma->vm_file = ps->arch.file;
+ /* insert into the special inode mapping list */
+ vma->vm_next_share = *head;
+ if (*head)
+ (*head)->vm_pprev_share = &vma->vm_next_share;
+ *head = vma;
+ vma->vm_pprev_share = head;
+ }
+#endif
return GM_SUCCESS;
}
@@ -155,6 +199,7 @@
if (ps->arch.ops_count == 0 || current->mm != ps->arch.mm)
return;
gm_always_assert (current->mm);
+ down_mmap_sem (¤t->mm->mmap_sem);
vma = current->mm->mmap;
while (vma)
{
@@ -175,4 +220,5 @@
gm_assert (gm_hash_find (ps->arch.ops_hash, vma->vm_ops) == NULL);
vma = vma->vm_next;
}
+ up_mmap_sem (¤t->mm->mmap_sem);
}
Index: gm/include/gm_auto_config.h.in
diff -u gm/include/gm_auto_config.h.in:1.64 gm/include/gm_auto_config.h.in:1.64.34.1
--- gm/include/gm_auto_config.h.in:1.64 Tue Apr 9 08:18:30 2002
+++ gm/include/gm_auto_config.h.in Fri Jun 21 05:57:21 2002
@@ -52,6 +52,9 @@
/* Define if you have the on_exit function. */
#undef HAVE_ON_EXIT
+/* Define if you have the <asm/rmap.h> header file. */
+#undef HAVE_ASM_RMAP_H
+
/* Define if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
Index: gm/libgm/gm_fork_system.c
diff -u gm/libgm/gm_fork_system.c:1.21 gm/libgm/gm_fork_system.c:1.21.156.1
--- gm/libgm/gm_fork_system.c:1.21 Wed Oct 3 05:29:58 2001
+++ gm/libgm/gm_fork_system.c Thu Jun 20 09:02:45 2002
@@ -83,7 +83,8 @@
-#if (GM_ENABLE_FORK_SYSTEM == 0)
+/* always use our custom system() for Linux to minimize fork() use */
+#if (GM_ENABLE_FORK_SYSTEM == 0) || GM_OS_LINUX
int
system (const char *cmd)
{