Added function get_memory_map_etc() which works similar to

get_memory_map(), but has a saner semantics and allows specifying a
team.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26600 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2008-07-24 04:07:14 +00:00
parent 0ae1957465
commit 6e60a6ac03
2 changed files with 62 additions and 24 deletions

View File

@ -151,6 +151,9 @@ extern status_t lock_memory(void *buffer, size_t numBytes, uint32 flags);
extern status_t unlock_memory_etc(team_id team, void *address, extern status_t unlock_memory_etc(team_id team, void *address,
size_t numBytes, uint32 flags); size_t numBytes, uint32 flags);
extern status_t unlock_memory(void *buffer, size_t numBytes, uint32 flags); extern status_t unlock_memory(void *buffer, size_t numBytes, uint32 flags);
extern status_t get_memory_map_etc(team_id team, const void *address,
size_t numBytes, physical_entry *table,
uint32* _numEntries);
extern long get_memory_map(const void *buffer, ulong size, extern long get_memory_map(const void *buffer, ulong size,
physical_entry *table, long numEntries); physical_entry *table, long numEntries);
extern area_id map_physical_memory(const char *areaName, extern area_id map_physical_memory(const char *areaName,

View File

@ -5100,13 +5100,21 @@ unlock_memory(void *address, size_t numBytes, uint32 flags)
} }
/*! According to the BeBook, this function should always succeed. /*! Similar to get_memory_map(), but also allows to specify the address space
This is no longer the case. for the memory in question and has a saner semantics.
Returns \c B_OK when the complete range could be translated or
\c B_BUFFER_OVERFLOW, if the provided array wasn't big enough. In either
case the actual number of entries is written to \c *_numEntries. Any other
error case indicates complete failure; \c *_numEntries will be set to \c 0
in this case.
*/ */
long status_t
get_memory_map(const void *address, ulong numBytes, physical_entry *table, get_memory_map_etc(team_id team, const void *address, size_t numBytes,
long numEntries) physical_entry *table, uint32* _numEntries)
{ {
uint32 numEntries = *_numEntries;
*_numEntries = 0;
vm_address_space *addressSpace; vm_address_space *addressSpace;
addr_t virtualAddress = (addr_t)address; addr_t virtualAddress = (addr_t)address;
addr_t pageOffset = virtualAddress & (B_PAGE_SIZE - 1); addr_t pageOffset = virtualAddress & (B_PAGE_SIZE - 1);
@ -5116,17 +5124,20 @@ get_memory_map(const void *address, ulong numBytes, physical_entry *table,
addr_t offset = 0; addr_t offset = 0;
bool interrupts = are_interrupts_enabled(); bool interrupts = are_interrupts_enabled();
TRACE(("get_memory_map(%p, %lu bytes, %ld entries)\n", address, numBytes, TRACE(("get_memory_map_etc(%ld, %p, %lu bytes, %ld entries)\n", team,
numEntries)); address, numBytes, numEntries));
if (numEntries == 0 || numBytes == 0) if (numEntries == 0 || numBytes == 0)
return B_BAD_VALUE; return B_BAD_VALUE;
// in which address space is the address to be found? // in which address space is the address to be found?
if (IS_USER_ADDRESS(virtualAddress)) if (IS_USER_ADDRESS(virtualAddress)) {
addressSpace = thread_get_current_thread()->team->address_space; if (team == B_CURRENT_TEAM)
else addressSpace = vm_get_current_user_address_space();
addressSpace = vm_kernel_address_space(); else
addressSpace = vm_get_address_space(team);
} else
addressSpace = vm_get_kernel_address_space();
if (addressSpace == NULL) if (addressSpace == NULL)
return B_ERROR; return B_ERROR;
@ -5163,7 +5174,7 @@ get_memory_map(const void *address, ulong numBytes, physical_entry *table,
// need to switch to the next physical_entry? // need to switch to the next physical_entry?
if (index < 0 || (addr_t)table[index].address if (index < 0 || (addr_t)table[index].address
!= physicalAddress - table[index].size) { != physicalAddress - table[index].size) {
if (++index + 1 > numEntries) { if ((uint32)++index + 1 > numEntries) {
// table to small // table to small
status = B_BUFFER_OVERFLOW; status = B_BUFFER_OVERFLOW;
break; break;
@ -5181,21 +5192,45 @@ get_memory_map(const void *address, ulong numBytes, physical_entry *table,
if (interrupts) if (interrupts)
map->ops->unlock(map); map->ops->unlock(map);
// close the entry list if (status != B_OK)
return status;
if (status == B_OK) { if ((uint32)index + 1 > numEntries) {
// if it's only one entry, we will silently accept the missing ending *_numEntries = index;
if (numEntries == 1) return B_BUFFER_OVERFLOW;
return B_OK;
if (++index + 1 > numEntries)
return B_BUFFER_OVERFLOW;
table[index].address = NULL;
table[index].size = 0;
} }
return status; *_numEntries = index + 1;
return B_OK;
}
/*! According to the BeBook, this function should always succeed.
This is no longer the case.
*/
long
get_memory_map(const void *address, ulong numBytes, physical_entry *table,
long numEntries)
{
uint32 entriesRead = numEntries;
status_t error = get_memory_map_etc(B_CURRENT_TEAM, address, numBytes,
table, &entriesRead);
if (error != B_OK)
return error;
// close the entry list
// if it's only one entry, we will silently accept the missing ending
if (numEntries == 1)
return B_OK;
if (entriesRead + 1 > (uint32)numEntries)
return B_BUFFER_OVERFLOW;
table[entriesRead].address = NULL;
table[entriesRead].size = 0;
return B_OK;
} }