English Amiga Board


Go Back   English Amiga Board > Coders > Coders. System

 
 
Thread Tools
Old 12 July 2024, 03:07   #1
Steam Ranger
Registered User
 
Steam Ranger's Avatar
 
Join Date: May 2022
Location: Adelaide, South Australia, Australia
Posts: 209
Design idea behind AllocMem()?

Plain and simple, why did the devs implement AllocMem()?

AllocVec() was implemented with 2.0, and it has the same capability as AllocMem(), while being easier to use for the assembly programmer and being more similar to the C standard library functions. Seen as AllocVec() was implemented so quickly, I have to wonder, why did the devs bother with AllocMem() in the first place?
Steam Ranger is offline  
Old 12 July 2024, 04:18   #2
alkis
Registered User
 
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 727
Probably because "metadata" is waste of memory. A1000 came with 256K ram. Also UNIX had a free with size up until 1979.

https://stackoverflow.com/questions/...22002#24222002
alkis is offline  
Old 12 July 2024, 04:20   #3
Samurai_Crow
Total Chaos forever!
 
Samurai_Crow's Avatar
 
Join Date: Aug 2007
Location: Waterville, MN, USA
Age: 49
Posts: 2,213
AllocMem() was designed around the specific constraints of Exec.library and was never intended to be the memory allocator for the whole system. I remember this because when the AmigaOS4 dev team announced the new slab allocator, the original author was there at the DevCon (Carl Sassenrath?) and announced this publicly.

AllocVec() was just a linked-list wrapper around AllocMem(). Without AllocMem(), AllocVec() wouldn't work.

Sidenotes:
AllocVec() allocations place a pointer in the header of the allocated memory, making it waste chip RAM and slowing deallocation operations if that's where they are located.

I'd prefer using a custom allocator wrapping AllocMem() rather than AllocVec() for most applications anyway. Possibly a slab allocator that honors cache row alignment instead, for example. That way the context header (allocated in MEMF_ANY RAM) would be an array of pointers per slab, reducing the overhead of the allocation and deallocation since there would be one list node per slab of allocations rather than a list node per individual allocation.
Samurai_Crow is offline  
Old 12 July 2024, 04:27   #4
Thorham
Computer Nerd
 
Thorham's Avatar
 
Join Date: Sep 2007
Location: Rotterdam/Netherlands
Age: 48
Posts: 3,876
Quote:
Originally Posted by alkis View Post
Probably because "metadata" is waste of memory.
Except that you still have to store the size anyway or you can't free allocated memory.
Thorham is offline  
Old 12 July 2024, 05:35   #5
Docent
Registered User
 
Join Date: Mar 2019
Location: Poland
Posts: 65
Exec memory management works on a list of free memory chunks and do not maintain information about allocated memory. In such design freeing allocated memory and adding it to free memory list requires specifying both the pointer to allocated memory and its size.

In 1984 when memory management was implemented, there was only 256kb of ram available, so system could not afford to store information on allocated size as it would cause 4 bytes overhead per allocation. AllocVec appeared in 1990, when all amigas shipped with minimum 512kb of ram, so additional 4 bytes wasnt such an issue.
Docent is offline  
Old 12 July 2024, 05:41   #6
Minuous
Coder/webmaster/gamer
 
Minuous's Avatar
 
Join Date: Oct 2001
Location: Canberra/Australia
Posts: 2,695
It's often the case that there are many allocations made of the same size, eg. when working with lists. Storing the size in each allocation is unnecessary and wasteful in such situations.
Minuous is offline  
Old 12 July 2024, 06:14   #7
Docent
Registered User
 
Join Date: Mar 2019
Location: Poland
Posts: 65
Quote:
Originally Posted by Samurai_Crow View Post
AllocMem() was designed around the specific constraints of Exec.library and was never intended to be the memory allocator for the whole system. I remember this because when the AmigaOS4 dev team announced the new slab allocator, the original author was there at the DevCon (Carl Sassenrath?) and announced this publicly.
Exec memory management was designed around machine constraints, not exec itself. I never heard about other memory allocators in exec planned for original system. The fact is, AllocMem was often misused as a general memory allocator in an application and it caused significant memory fragmentation, especially when allocating/freeing a lot of small chunks of memory (KS 3.0 introduced pool management to help solve this problem)
The indended use of exec memory management in a task was to allocate some memory from the system via AllocMem and then maintain other allocations from already allocated block with Allocate/Deallocate calls.
Quote:
Originally Posted by Samurai_Crow View Post
AllocVec() was just a linked-list wrapper around AllocMem(). Without AllocMem(), AllocVec() wouldn't work.
This is not true. AllocVec/FreeVec is not a linked-list wrapper - it is just a small wrapper that works on top of AllocMem/FreeMem. It basically allocates requested memory block size+4 from AllocMem and stores the size at the beginning of allocated block. FreeVec takes stored allocated block size from provided memory pointer and calls FreeMem.
Quote:
Originally Posted by Samurai_Crow View Post
AllocVec() allocations place a pointer in the header of the allocated memory, making it waste chip RAM and slowing deallocation operations if that's where they are located.
It is not a pointer but the size of allocated block.
Docent is offline  
Old 12 July 2024, 07:14   #8
Samurai_Crow
Total Chaos forever!
 
Samurai_Crow's Avatar
 
Join Date: Aug 2007
Location: Waterville, MN, USA
Age: 49
Posts: 2,213
Quote:
Originally Posted by Docent View Post
Exec memory management was designed around machine constraints, not exec itself. I never heard about other memory allocators in exec planned for original system. The fact is, AllocMem was often misused as a general memory allocator in an application and it caused significant memory fragmentation, especially when allocating/freeing a lot of small chunks of memory (KS 3.0 introduced pool management to help solve this problem)
Slab allocation just takes memory pools to the next level by grouping same-size allocations together, where each size uses a different pool. On AmigaOS 4, the PPC processors all have an MMU so the puddle size is generally the page size of the MMU and allocates a page at a time using a second-stage allocator. (At least that's how I would have done it.)
Samurai_Crow is offline  
Old 12 July 2024, 13:25   #9
mschulz
Registered User
 
Join Date: Nov 2018
Location: Germany
Posts: 112
Quote:
Originally Posted by Thorham View Post
Except that you still have to store the size anyway or you can't free allocated memory.
Of course you can. Exec does not maintain a list of allocated blocks. Instead it maintains single linked list of free blocks. In this design, as Docent wrote, you need to know address and size of block to be freed as it must be relinked to free mem chunk list and eventually merged.

BTW. As a side effect of such memory management by exec it is perfectly possible to free only an arbitrary portion of memory allocated as a single block previously. This works well as long as one correctly frees the remaining parts afterwards.
mschulz is offline  
Old 12 July 2024, 16:27   #10
SpeedGeek
Moderator
 
SpeedGeek's Avatar
 
Join Date: Dec 2010
Location: Wisconsin USA
Age: 60
Posts: 848
Quote:
Originally Posted by Docent View Post
Exec memory management was designed around machine constraints, not exec itself. I never heard about other memory allocators in exec planned for original system. The fact is, AllocMem was often misused as a general memory allocator in an application and it caused significant memory fragmentation, especially when allocating/freeing a lot of small chunks of memory (KS 3.0 introduced pool management to help solve this problem)
The indended use of exec memory management in a task was to allocate some memory from the system via AllocMem and then maintain other allocations from already allocated block with Allocate/Deallocate calls.

This is not true. AllocVec/FreeVec is not a linked-list wrapper - it is just a small wrapper that works on top of AllocMem/FreeMem. It basically allocates requested memory block size+4 from AllocMem and stores the size at the beginning of allocated block. FreeVec takes stored allocated block size from provided memory pointer and calls FreeMem.

It is not a pointer but the size of allocated block.

The fragmentation problem is not caused by Allocmem, rather it is caused by the misuse of Allocmem. The SAS C linker was rather notorious at creating programs with a large number of hunks. AllocVec does not prevent the memory fragmentation problem, it's just a more convenient way to allocate and release memory which only the user program can do safely. Amiga OS was just intended to keep track of the available free memory in a multitasking environment with the so called "Well Behaved" user programs allocating and/or releasing memory as needed.

Last edited by SpeedGeek; 12 July 2024 at 22:42.
SpeedGeek is offline  
Old 12 July 2024, 17:29   #11
Docent
Registered User
 
Join Date: Mar 2019
Location: Poland
Posts: 65
Quote:
Originally Posted by SpeedGeek View Post
The fragmentation problem is not caused by Allocmem, rather it is caused by the misuse of Allocmem.
You quoted my earlier answer with your message, but I did not write that AllocMem caused memory fragmentation
Quote:
Originally Posted by SpeedGeek View Post
AllocVec does not prevent the memory fragmentation problem,
and I did not write that AllocVec prevents memory fragmentation either.
Docent is offline  
Old 12 July 2024, 18:58   #12
paraj
Registered User
 
paraj's Avatar
 
Join Date: Feb 2017
Location: Denmark
Posts: 1,261
It has already been said, but I think it's worth spelling out: AllocMem/FreeMem is strictly more "powerful" than AllocVec/FreeVec. You can implement AllocVec on your own (or anything else you might like) in terms of AllocMem, but not the other way round.

AllocMem is the obvious, minimal thing you would implement in a small kernel at this point in time. The developers were likely imagining you would either be using a higher level language to handle allocations or write your own wrapper if you were using assembly and wanted convenience rather than lower memory usage.

You could ask similar questions for why CreateIORequest was not initially available in exec for example.
paraj is offline  
Old 12 July 2024, 19:06   #13
Thomas Richter
Registered User
 
Join Date: Jan 2019
Location: Germany
Posts: 3,355
Quote:
Originally Posted by Steam Ranger View Post
Seen as AllocVec() was implemented so quickly, I have to wonder, why did the devs bother with AllocMem() in the first place?
That we have both AllocVec() and AllocMem() is more a historical accident. AllocMem() was intended more in the directio of brk() under *ix operating systems which allocates a large chunk of memory for a process which then splits it up into pieces itself. Then Tripos came and brought its own memory allocation functions, getvec() namely, eachable through the GlobVec of BCPL. This was quickly bolted on top of AllocMem() though works otherwise according to the semantics of AllocVec() already. Kick 36 moved then the BCPL/Tripos function getvec() into AllocVec() of the exec.library, keeping the semantics of the function.


Memory pool functions closer to what was originally indented also became available in v36 as AllocPooled()/FreePooled() to allow processes to manage memory more efficiently.


Concerning memory management, the situation is already quite messy. Processes can keep lists of allocated memory that is automatically released when they go down, though this feature is rarely used. This is AllocEntry() and the process memory list.



Then we have the AllocRemember() functions of intuition which work around the limitations of exec, though without really adding pools, just tagging memory, and then at the level of the icon.library we have a third memory adminsitration function.


In v45 and v47, layers and graphics became smarter to pool their cliprects and regions in lists such that not every allocation needs to go down to exec, helping to reduce the fragmentation problem a bit.



For today's requirements, I would just leave AllocEntry() and the intuition and icon functions alone, and programs could/should use the AllocPooled() functions of exec.


Most C compilers implement memory pools by their own, and implement malloc() through their own memory pools. So malloc() does not sit directly on top of AllocMem(), but through another layer in the C standard library. Unfortunately, that layer is typically different from AllocPooled() to be able to implement realloc.
Thomas Richter is offline  
Old 12 July 2024, 19:09   #14
Thomas Richter
Registered User
 
Join Date: Jan 2019
Location: Germany
Posts: 3,355
Quote:
Originally Posted by SpeedGeek View Post
The SAS C linker was rather notorious at creating programs with a large number of hunks.

Actually, make this the Lattic BLink linker or even more concretely the default settings of the Lattice C compiler. This problem was long gone when SAS bought the Lattice compiler. Early Lattic versions placed each stub function from amiga.lib and each program unit into its own hunk, but those times were long gone already with later versions of Lattice C.

Last edited by SpeedGeek; 12 July 2024 at 22:45.
Thomas Richter is offline  
Old 12 July 2024, 19:15   #15
Thomas Richter
Registered User
 
Join Date: Jan 2019
Location: Germany
Posts: 3,355
Quote:
Originally Posted by mschulz View Post
BTW. As a side effect of such memory management by exec it is perfectly possible to free only an arbitrary portion of memory allocated as a single block previously. This works well as long as one correctly frees the remaining parts afterwards.

That's perfectly illegal. The reason being that this requires knowledge of the internal rounding algorithms of exec, and it also causes headaches of all kinds of debugging tools. In short. "DON'T".


Some versions of the layers.library did this, causing a lot of issues in mungwall that caused debugging headaches even in 3.1.4. Layers was already fixed to avoid this in v40, but mungwall still had a workaround in it.


You find interface requirements for AllocMem() and FreeMem() in the documentation of PoolMem (on Aminet) for example. Most of what is said there is pretty obvious, and one of the important points is "don't break up one AllocMem() into multiple FreeMem()s", this is really asking for trouble and is creating forward compatiblity issues.


Just to give you one idea: Typically, you would like to allocate memory aligned to at least cache line boundaries, which requires a change of the exec memory alignment policy. With such changes, any hacks that splits up one allocation into multiple releases are going to break.
Thomas Richter is offline  
Old 12 July 2024, 19:37   #16
paraj
Registered User
 
paraj's Avatar
 
Join Date: Feb 2017
Location: Denmark
Posts: 1,261
Quote:
Originally Posted by Thomas Richter View Post
That's perfectly illegal. The reason being that this requires knowledge of the internal rounding algorithms of exec, and it also causes headaches of all kinds of debugging tools. In short. "DON'T".


Some versions of the layers.library did this, causing a lot of issues in mungwall that caused debugging headaches even in 3.1.4. Layers was already fixed to avoid this in v40, but mungwall still had a workaround in it.


You find interface requirements for AllocMem() and FreeMem() in the documentation of PoolMem (on Aminet) for example. Most of what is said there is pretty obvious, and one of the important points is "don't break up one AllocMem() into multiple FreeMem()s", this is really asking for trouble and is creating forward compatiblity issues.


Just to give you one idea: Typically, you would like to allocate memory aligned to at least cache line boundaries, which requires a change of the exec memory alignment policy. With such changes, any hacks that splits up one allocation into multiple releases are going to break.

While I agree that it's probably not a good idea, the documentation for FreeMem just says that "freeing partial blocks back into the system pool is unwise" not "illegal" - I know how to read between the lines, but they should have used stronger language instead of being clever. Yes, it also says it will round it to "a multiple of the system memory chunk size", but that chunk size being 8 is effectively set in stone by "Hyrum's Law" of interfaces.


IOW you shouldn't (for your own sake) FreeMem in the middle of a block depending on the 8-byte chunk size, but on the other hand it will work, and have to keep working in 3.x.
paraj is offline  
Old 13 July 2024, 17:23   #17
SpeedGeek
Moderator
 
SpeedGeek's Avatar
 
Join Date: Dec 2010
Location: Wisconsin USA
Age: 60
Posts: 848
Quote:
Originally Posted by Docent View Post
You quoted my earlier answer with your message, but I did not write that AllocMem caused memory fragmentation and I did not write that AllocVec prevents memory fragmentation either.
You wrote:

"The fact is, AllocMem was often misused as a general memory allocator in an application and it caused significant memory fragmentation..."

Because of the way you wrote this, it could be interpreted as Allocmem causing the memory fragmentation. But thanks for clarifying that you did not intend it to be interpreted that way.

Quote:
Originally Posted by Thomas Richter View Post
Actually, make this the Lattic BLink linker or even more concretely the default settings of the Lattice C compiler. This problem was long gone when SAS bought the Lattice compiler. Early Lattic versions placed each stub function from amiga.lib and each program unit into its own hunk, but those times were long gone already with later versions of Lattice C.
RSCP v1.10 was compiled and linked with SAS C 5.x and it had approx. 10 hunks. The more recently updated versions were compiled and linked with SAS C 6.58 and they have 3 hunks. I order to get the 3 hunks I used the SMALLCODE and SMALLDATA options. They are not the default options for the Slink linker and AFAIK the old Blink linker did not offer these options.

As far as the old Lattice C compiler and linker, I don't know exactly how it compares to SAS C 5.x but I doubt it could do any better.
SpeedGeek is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
Is it possible to reduce an AllocMem() chunk? 8bitbubsy Coders. Asm / Hardware 34 12 October 2023 19:51
Accelerator board + Zorro II: good idea bad idea ? Clad support.Hardware 4 15 July 2023 15:00
Idea for the vampire owners - just an idea Syntrax support.Hardware 18 19 January 2019 13:08
How not to design a console... tonyyeb Retrogaming General Discussion 26 26 August 2009 02:48
New PPC design Brass support.Hardware 9 19 December 2007 14:50

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 12:48.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.15141 seconds with 13 queries