How much memory FreeBSD/amd64 can allocate to an i386 binary ?

A 32-bit process can access 4 GB of virtual memory map. However, that map is then split into 2 pieces: 2 GB for the kernel, 2 GB for the process itself. It's the same setup on just about every PC-based OS (Windows, Linux, MacOS X, the BSDs, etc).

If a process needs to access more than 2 GB of the virtual memory map, then it needs to resort to various tricks like PAE, memory thunking, bounce buffers, or reconfiguring the kernel/user split (aka large memory support).

The first and last options are things the user can do. The others are things only the program devs can do.

Not sure how to change the kernel/user split in FreeBSD, but it is possible to use a 1/3 split instead of the standard 2/2 split. As you discovered, it's possible to add a flag to the Windows boot loader to change this.
 
phoenix - sorry, but that is not entirely correct if my memory serves me right.

MacOS gives you almost 4GB, the "kernel" mapped in is a 64KB address map switcher.

PAE can only allow the kernel to have MMU tables which contain more than 4GB. One process tops out at an address range of 4 GB no matter what, but you can now have several of these on your system. I would be happ to be corrected on this one.
 
So there are 2 operation modes for 32bit applications in 64bit OS:
- 2G/2G or 1G/3G split with "real" kernel in address space
- 4194240K/64K split with address map switcher

This leads to a question:
What is the memory limit for native 32bit FreeBSD applications?
What split model uses FreeBSD for its 32bit compatibility mode?

Wine is nothing else than an application who offers its "guest" the windows API's and translates the API calls to the native kernel.
So wine is bound to the OS limitations too.
 
The 64KB switch code is special to how Mach (and thus MacOS X) go about things. You can not configure that on FreeBSD or any Unix I know of.
 
I have written some max memory values earlier in this thread.
Based on this values I guess both linux and windows 64bit doing some similar thing.

Don't get me wrong. I don't think FreeBSD should have such mechanism to squeeze the last byte out of the 32bit memory model.
If an application needs huge amounts of memory - it should go to 64bit.
 
So there are 2 operation modes for 32bit applications in 64bit OS:
- 2G/2G or 1G/3G split with "real" kernel in address space
- 4194240K/64K split with address map switcher

This leads to a question:
What is the memory limit for native 32bit FreeBSD applications?
What split model uses FreeBSD for its 32bit compatibility mode?

Not sure about 32-bit apps on 64-bit OS (would assume it's the same as for a 32-bit OS, but you know what they say about assumptions), but a 32-bit install of FreeBSD uses a 2G/2G mapping. There's been talk on the mailing lists this year about switching to a 1G/3G mapping. Not sure if that change was ever made or not.
 
How did you manage to get this number? Wine itself limits applications to 2 or 3 Gb depending on LARGE_ADDRESS_AWARE flag.
I just run the test program who allocates memory until it gets an "out of memory" exception.
The limit of 2 or 3 or 4 Gb depends on set compiler switches:
Code:
#ifdef __i386__
...
static void *address_space_limit = (void *)0xc0000000;  /* top of the total available address space */
static void *user_space_limit    = (void *)0x7fff0000;  /* top of the user address space */
static void *working_set_limit   = (void *)0x7fff0000;  /* top of the current working set */
...
#elif defined(__x86_64__)
...
static void *address_space_limit = (void *)0x7fffffff0000;
static void *user_space_limit    = (void *)0x7fffffff0000;
static void *working_set_limit   = (void *)0x7fffffff0000;
...
#else
...
static void *address_space_limit;
static void *user_space_limit;
static void *working_set_limit;
...
#endif  /* __i386__ */
...

...
#if !defined(__i386__) && !defined(__x86_64__)
...
#ifdef _WIN64
    address_space_limit = (void *)(((1UL << 47) - 1) & ~page_mask);
#else
    address_space_limit = (void *)~page_mask;
#endif
    user_space_limit = working_set_limit = address_space_limit;
#endif
I do not know what switches were set during the wine compilation.

0xc0000000 = 3Gb if set __i386__ (wine32 on 32 bit OS ?)
0x7fffffff0000 = 128Tb if set __x86_64__ (wine64 on 64 bit OS ?)
~page_mask = calculated from current memory model (maybe 4Gb), if none switch set. (wineXX on 64 bit OS ?)
 
To clearify: that is about an i386 binary on an amd64 host, yes?
 
To clearify: that is about an i386 binary on an amd64 host, yes?

Yes, nothing there makes sense otherwise.

I do not know what switches were set during the wine compilation.

I believe -m32 compiler option also defines __i386__, so address_space_limit = (void *)~page_mask line isn't relevant for 32-bit Wine apps on amd64. I don't know what it is supposed to do, that would require some digging through commit history. Presumably it will be compiled on ARM, but I think it actually predates Wine's ARM port.
 
Wine in particular has the problem of emulating some of the windows process memory layout, so the GB must have holes for wine and reserved areas anyway, right?
 
I'm not quite sure whether Wine reserves anything for heap immediately on start. One thing I noticed is that recompiling Wine with user_space_limit set to 3 Gb reduced allocated virtual memory by roughly 1 Gb for two problematic applications (I complained earlier in this thread about them), while actual memory usage is unaffected. Didn't expect that at all.

Note also that Wine's heap is a distinct entity from jemalloc's heap, so there is some possibility for pathological interactions. Most likely it is just Wine misbehaving though.
 
To clearify: that is about an i386 binary on an amd64 host, yes?
Yes, 32bit Windows binary on amd64 Linux system. Is wine itself a 32 or 64 bit binary? I don't know! I am also not remember the Wine version.
Yes, nothing there makes sense otherwise.
I believe -m32 compiler option also defines __i386__, so address_space_limit = (void *)~page_mask line isn't relevant for 32-bit Wine apps on amd64.
That's the drawback of precompiled binary packages. It's hard to say what options the packager used.
I don't know what it is supposed to do, that would require some digging through commit history. Presumably it will be compiled on ARM, but I think it actually predates Wine's ARM port.
Wine on ARM? Sounds funny. Since there is no real Windows on ARM (except Win10 for RPi3), there are no windows programms for ARM.
Wine in particular has the problem of emulating some of the windows process memory layout, so the GB must have holes for wine and reserved areas anyway, right?
Sure. But that's the case on real Windows too. You can't do a malloc(3*1024*1024*1024); on real Windows nor on Wine.
I'm not quite sure whether Wine reserves anything for heap immediately on start. One thing I noticed is that recompiling Wine with user_space_limit set to 3 Gb reduced allocated virtual memory by roughly 1 Gb for two problematic applications (I complained earlier in this thread about them), while actual memory usage is unaffected. Didn't expect that at all. Note also that Wine's heap is a distinct entity from jemalloc's heap, so there is some possibility for pathological interactions. Most likely it is just Wine misbehaving though.
If you force Wine to 3Gb, it takes 3Gb. I am not surprised. You are talking about virtual memory - is that just address space or allocated real physical memory?
 
You are talking about virtual memory - is that just address space or allocated real physical memory

Address space, the memory which application requested but didn't necessarily try to read or write. In other words, if you request too much memory mmap refuses to work because the system is simply out of valid pointers. It's kinda funny, since it's usually considered a theoretical problem.

If you force Wine to 3Gb, it takes 3Gb. I am not surprised.

You are not paying attention: setting limit to 3 Gb makes Wine process request 2 Gb instead of 3-3.5 Gb on start with two separate games. Actual memory usage never exceeds 1.5 Gb, so there is no reason to think they require LARGE_ADDRESS_AWARE flag and, of course, it's not set out-of-the-box — it's not an issue on Windows.
 
Address space, the memory which application requested but didn't necessarily try to read or write. In other words, if you request too much memory mmap refuses to work because the system is simply out of valid pointers. It's kinda funny, since it's usually considered a theoretical problem.
Do I understand right? Wine gets the full 4Gb address space from host for later ram usage, and if the guest need address space for everything else (maybe memory mapped files) this fails, because wine can not get more address space.
Sounds strange!
You are not paying attention: setting limit to 3 Gb makes Wine process request 2 Gb instead of 3-3.5 Gb on start with two separate games. Actual memory usage never exceeds 1.5 Gb, so there is no reason to think they require LARGE_ADDRESS_AWARE flag and, of course, it's not set out-of-the-box — it's not an issue on Windows.
Sorry if I misunderstand you. It's a heavy topic.
 
Wine gets the full 4Gb address space from host for later ram usage, and if the guest need address space for everything else (maybe memory mapped files) this fails, because wine can not get more address space.

The issue is that some Wine component, most likely wined3d, requests much more memory than it actually cares to use to the point it prevents OpenGL driver from allocating memory for its own needs (like loading textures or compiling shaders). The driver eventually returns GL_OUT_OF_MEMORY error and crashes with nonsensical stack trace. Why this happens is a whole other question. I can't offer you any explanation because I do not know that in the first place.
 
This workaround has been working until Wine 5.9 (we are at the 8.0 version of Wine today).

I was changing that user space limit to 3 GB and had been able to play and finish so many games but since the Wine 5.9 version, doing :
- char *user_space_limit = (char *)0x7ffe0000;
+ char *user_space_limit = (char *)0xbffe0000;
in mmap.c is making Wine immediatly crash at launch with error allocating memory.

I kept using the nvidia-driver-470 (because 510 is also causing Wine to crash at launch, this is a known issue https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=263475) and kept using the Wine 5.8 in order to keep playing to bigger games than 2000's games and 2D's over the years.

Actually, I don't know what has been changed but the mmap.c file is different and this patch isn't fixing the issue anymore.
Back to older games.
 
Back
Top