From 02cceebe403215977ae406355ba882ba94ae1151 Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Tue, 5 Mar 2013 00:23:26 +0100 Subject: [PATCH] team: randomize position of team user data When forking a process team user data area is not cloned but a new one is created instead. However, the new one has to be at exactly the same address parent's team user data area is. When process is exec then team user data area may be recreated at random position. This patch also make sure that instances of struct user_thread in team user data are each in separate cache line in order to prevent false sharing since these data are very likely to be accessed simultaneously from threads executing on different CPUs. This change however reduces the number of threads process can create. It is fixed by reserving 512kB of address space in case team user data area needs to grow. --- src/system/kernel/team.cpp | 43 +++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/src/system/kernel/team.cpp b/src/system/kernel/team.cpp index 381be36458..974719b81a 100644 --- a/src/system/kernel/team.cpp +++ b/src/system/kernel/team.cpp @@ -158,6 +158,9 @@ static int32 sUsedTeams = 1; static TeamNotificationService sNotificationService; +static const size_t kTeamUserDataReservedSize = 128 * B_PAGE_SIZE; +static const size_t kTeamUserDataInitialSize = 4 * B_PAGE_SIZE; + // #pragma mark - TeamListIterator @@ -1324,23 +1327,40 @@ remove_team_from_group(Team* team) static status_t -create_team_user_data(Team* team) +create_team_user_data(Team* team, void* exactAddress = NULL) { void* address; - size_t size = 4 * B_PAGE_SIZE; + uint32 addressSpec; + + if (exactAddress != NULL) { + address = exactAddress; + addressSpec = B_EXACT_ADDRESS; + } else + addressSpec = B_RANDOMIZED_BASE_ADDRESS; + + status_t result = vm_reserve_address_range(team->id, &address, addressSpec, + kTeamUserDataReservedSize, RESERVED_AVOID_BASE); + virtual_address_restrictions virtualRestrictions = {}; - virtualRestrictions.address = (void*)KERNEL_USER_DATA_BASE; - virtualRestrictions.address_specification = B_BASE_ADDRESS; + if (result == B_OK || exactAddress != NULL) { + if (exactAddress != NULL) + virtualRestrictions.address = exactAddress; + else + virtualRestrictions.address = address; + virtualRestrictions.address_specification = B_EXACT_ADDRESS; + } else + virtualRestrictions.address_specification = B_RANDOMIZED_ANY_ADDRESS; + physical_address_restrictions physicalRestrictions = {}; - team->user_data_area = create_area_etc(team->id, "user area", size, - B_FULL_LOCK, B_READ_AREA | B_WRITE_AREA, 0, 0, &virtualRestrictions, - &physicalRestrictions, &address); + team->user_data_area = create_area_etc(team->id, "user area", + kTeamUserDataInitialSize, B_FULL_LOCK, B_READ_AREA | B_WRITE_AREA, 0, 0, + &virtualRestrictions, &physicalRestrictions, &address); if (team->user_data_area < 0) return team->user_data_area; team->user_data = (addr_t)address; team->used_user_data = 0; - team->user_data_size = size; + team->user_data_size = kTeamUserDataInitialSize; team->free_user_threads = NULL; return B_OK; @@ -1352,6 +1372,9 @@ delete_team_user_data(Team* team) { if (team->user_data_area >= 0) { vm_delete_area(team->id, team->user_data_area, true); + vm_unreserve_address_range(team->id, (void*)team->user_data, + kTeamUserDataReservedSize); + team->user_data = 0; team->used_user_data = 0; team->user_data_size = 0; @@ -2035,7 +2058,7 @@ fork_team(void) while (get_next_area_info(B_CURRENT_TEAM, &areaCookie, &info) == B_OK) { if (info.area == parentTeam->user_data_area) { // don't clone the user area; just create a new one - status = create_team_user_data(team); + status = create_team_user_data(team, info.address); if (status != B_OK) break; @@ -3360,7 +3383,7 @@ team_allocate_user_thread(Team* team) while (true) { // enough space left? - size_t needed = ROUNDUP(sizeof(user_thread), 8); + size_t needed = ROUNDUP(sizeof(user_thread), 128); if (team->user_data_size - team->used_user_data < needed) { // try to resize the area if (resize_area(team->user_data_area,