Instead of using a bitmap or a stack you can use a linked list. This has several advantages.
1. It is as fast a stack (to allocate/deallocate you just manipulate pointers)
2. Finding where memory is in the list can be done in constant time. If you have a big array with one entry per page, then the ith page is in the ith array spot. The linked list pointers can just point to other locations in the array.
3. If you use a doubly linked list, removing an element from the middle is easy.
4. It can be easily extended to also have information on the least recently used page. If whenever you allocate a page (or a page has just been loaded from disk), you move that page to the back of the list then the list will have all the free pages at the start and the back will be the allocated pages in LRU sequence. Then if you just have an extra variable that tells you how many free nodes you have at the beginning of the list, you can tell when you've run out of memory too.
5. If you have "reserved" memory (ie. memory that should not be paged to disk) then just don't add it to the end of the list when you allocate it.
The only drawback that I can see is if you want to allocate a contiguous chunk of memory you'd have to search for it.
