Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 11 Mar 1996 22:22:06 +0100 (MET)
From:      J Wunsch <j@uriah.heep.sax.de>
To:        freebsd-current@FreeBSD.org (FreeBSD-current users)
Subject:   system() broken while mmap()ing something
Message-ID:  <199603112122.WAA07526@uriah.heep.sax.de>

next in thread | raw e-mail | index | archive | help
There's been a long and ongoing discussion about the reasons why
recent XFree86(tm) servers don't run under FreeBSD-current.  With Xkb
enabled, they hang the entire system, or cause other weird behaviour.

All the other systems supported by XFree86 don't suffer from this, and
it's easily provable that it's not related to phkmalloc (e.g. by using
the original gnumalloc again).

David Dawes has been boiling down this to:

----- Forwarded message from David Dawes -----

From: David Dawes <dawes@rf900.physics.usyd.edu.au>
Message-Id: <199603111058.VAA20801@rf900.physics.usyd.edu.au>
Subject: Re: 3.1.2Db S3 freebsd-current
To: beta@XFree86.Org
Date: Mon, 11 Mar 1996 21:58:31 +1100 (EST)
In-Reply-To: <199603110802.JAA05393@uriah.heep.sax.de> from "J Wunsch" at Mar 11, 96 09:02:18 am

>Do i understand it right that the system() call happens while /dev/mem
>is kept mmap()ed inside the X server?  Perhaps this is something
>that's unique to the X server environment.  (Other programs might
>either not mmap /dev/mem at all, or at least, they don't fork.)

That is correct.  The mmap happens when the display is initialised.  The
system() call happens when the input devices are initialised, and this
happens after the display is initialised.

The mmap area isn't completely lost -- at least reads (I tried xwd -root)
are *almost* OK with the S3 server when using a 64k VGA aperture.

I've attached a test program that does demonstrate a problem.  The program
isn't what I originally had in mind.  This one mmaps the BIOS, and in three
phases it "writes" to it, and reads back the result.  Since the BIOS is
read-only, mismatches should occur in each phase, however on FreeBSD-current,
the last phase (after a system("/bin/ls > /tmp/l")) reports no mismatches.
On FreeBSD-2.0.5, mismatches are correctly reported at each phase.

David
-----------
#include <stdio.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

#define SIZE (4 * 1024)
#define BASE 0xC0000

main()
{
	int fd = -1;
	unsigned char *base = NULL;
	unsigned char *save = NULL;
	int i;
	int mismatch = 0;

	if ((fd = open("/dev/mem", O_RDWR)) < 0) {
		perror("can't open /dev/mem");
		exit(1);
	}
	base = (unsigned char *)mmap((caddr_t)0, SIZE, PROT_READ | PROT_WRITE,
				MAP_FILE, fd, (off_t)BASE);
	if ((int)base == -1) {
		perror("can't mmap vga memory");
		exit(1);
	}
#ifdef SAVE_NEEDED
	/* Save the existing memory contents */
	if ((save = (unsigned char *)malloc(SIZE)) == NULL) {
		perror("malloc failed");
		exit(1);
	}
	memcpy(save, base, SIZE);
#endif
	/* Write a pattern */
	for (i = 0; i < SIZE; i++)
		base[i] = (i & 0xFF) ^ (i >> 8);
	/* Read it back */
	for (i = 0; i < SIZE; i++)
		if (base[i] != ((i & 0xFF) ^ (i >> 8))) {
#ifdef VERBOSE
			printf("before: byte %5d doesn't match -- %3d != %3d\n",
				i, base[i], (i & 0xFF) ^ (i >> 8));
#endif
			mismatch++;
		}
	printf("before: %5d mismatches\n", mismatch);
	/* Clear the pattern */
	memset(base, 0, SIZE);
	/* Write a pattern */
	for (i = 0; i < SIZE; i++)
		base[i] = (i & 0xFF) ^ (i >> 8);
	/* Read it back */
	mismatch = 0;
	for (i = 0; i < SIZE; i++)
		if (base[i] != ((i & 0xFF) ^ (i >> 8))) {
#ifdef VERBOSE
			printf("middle: byte %5d doesn't match -- %3d != %3d\n",
				i, base[i], (i & 0xFF) ^ (i >> 8));
#endif
			mismatch++;
		}
	printf("middle: %5d mismatches\n", mismatch);
	/* Clear the pattern */
	memset(base, 0, SIZE);
	/* Run something harmless */
	system("/bin/ls > /tmp/l");
	/* Write a pattern */
	for (i = 0; i < SIZE; i++)
		base[i] = (i & 0xFF) ^ (i >> 8);
	/* Read it back */
	mismatch = 0;
	for (i = 0; i < SIZE; i++)
		if (base[i] != ((i & 0xFF) ^ (i >> 8))) {
#ifdef VERBOSE
			printf("after: byte %5d doesn't match -- %3d != %3d\n",
				i, base[i], (i & 0xFF) ^ (i >> 8));
#endif
			mismatch++;
		}
	printf("after: %5d mismatches\n", mismatch);
#ifdef SAVE_NEEDED
	/* unmap, remap, and restore the video memory */
	munmap(base, SIZE);
	base = (char *)mmap((caddr_t)0, SIZE, PROT_READ | PROT_WRITE,
				MAP_FILE, fd, (off_t)BASE);
	if ((int)base == -1) {
		perror("can't mmap vga memory");
		exit(1);
	}
	memcpy(base, save, SIZE);
#endif
	munmap(base, SIZE);
	exit(0);
}

----- End of forwarded message from David Dawes -----

-- 
cheers, J"org

joerg_wunsch@uriah.heep.sax.de -- http://www.sax.de/~joerg/ -- NIC: JW11-RIPE
Never trust an operating system you don't have sources for. ;-)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199603112122.WAA07526>