Add fork support
If fork() is called, clear all duplicated data that is invalid in the
child process.
Change-Id: I4e27198060db593c630c6337b7071dfbd0d80b83
Signed-off-by: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
[ROCm/ROCR-Runtime commit: f1f62d863c]
This commit is contained in:
@@ -36,6 +36,11 @@
|
||||
|
||||
static HSAuint64 *events_page = NULL;
|
||||
|
||||
void clear_events_page(void)
|
||||
{
|
||||
events_page = NULL;
|
||||
}
|
||||
|
||||
static bool IsSystemEventType(HSA_EVENTTYPE type)
|
||||
{
|
||||
// Debug events behave as signal events.
|
||||
|
||||
@@ -2928,3 +2928,67 @@ HSAKMT_STATUS fmm_set_mem_user_data(const void *mem, void *usr_data)
|
||||
vm_obj->user_data = usr_data;
|
||||
return HSAKMT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void fmm_clear_aperture(manageble_aperture_t *app)
|
||||
{
|
||||
while (app->vm_objects)
|
||||
vm_remove_object(app, app->vm_objects);
|
||||
|
||||
while (app->vm_ranges)
|
||||
vm_remove_area(app, app->vm_ranges);
|
||||
|
||||
}
|
||||
|
||||
/* This is a special funcion that should be called only from the child process
|
||||
* after a fork(). This will clear all vm_objects and mmaps duplicated from
|
||||
* the parent.
|
||||
*/
|
||||
void fmm_clear_all_mem(void)
|
||||
{
|
||||
uint32_t i;
|
||||
void *map_addr;
|
||||
|
||||
/* Nothing is initialized. */
|
||||
if (!gpu_mem)
|
||||
return;
|
||||
|
||||
fmm_clear_aperture(&cpuvm_aperture);
|
||||
|
||||
for (i = 0; i < gpu_mem_count; i++) {
|
||||
fmm_clear_aperture(&gpu_mem[i].gpuvm_aperture);
|
||||
fmm_clear_aperture(&gpu_mem[i].scratch_aperture);
|
||||
fmm_clear_aperture(&gpu_mem[i].scratch_physical);
|
||||
}
|
||||
|
||||
if (is_dgpu_mem_init) {
|
||||
fmm_clear_aperture(&svm.dgpu_aperture);
|
||||
fmm_clear_aperture(&svm.dgpu_alt_aperture);
|
||||
|
||||
/* Use the same dgpu range as the parent. If failed, then set
|
||||
* is_dgpu_mem_init to false. Later on dgpu_mem_init will try
|
||||
* to get a new range
|
||||
*/
|
||||
map_addr = mmap(dgpu_shared_aperture_base, (HSAuint64)(dgpu_shared_aperture_limit)-
|
||||
(HSAuint64)(dgpu_shared_aperture_base) + 1, PROT_NONE,
|
||||
MAP_ANONYMOUS | MAP_NORESERVE | MAP_PRIVATE | MAP_FIXED, -1, 0);
|
||||
|
||||
if (map_addr == MAP_FAILED) {
|
||||
munmap(dgpu_shared_aperture_base,
|
||||
(HSAuint64)(dgpu_shared_aperture_limit) -
|
||||
(HSAuint64)(dgpu_shared_aperture_base) + 1);
|
||||
|
||||
dgpu_shared_aperture_base = NULL;
|
||||
dgpu_shared_aperture_limit = NULL;
|
||||
is_dgpu_mem_init = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (all_gpu_id_array)
|
||||
free(all_gpu_id_array);
|
||||
|
||||
all_gpu_id_array_size = 0;
|
||||
all_gpu_id_array = NULL;
|
||||
|
||||
gpu_mem_count = 0;
|
||||
free(gpu_mem);
|
||||
}
|
||||
|
||||
@@ -95,4 +95,7 @@ extern int kmtIoctl(int fd, unsigned long request, void *arg);
|
||||
#define VOID_PTR_SUB(ptr,n) (void*)((uint8_t*)(ptr) - n)/*ptr - offset*/
|
||||
#define VOID_PTRS_SUB(ptr1,ptr2) (uint64_t)((uint8_t*)(ptr1) - (uint8_t*)(ptr2)) /*ptr1 - ptr2*/
|
||||
|
||||
void clear_events_page(void);
|
||||
void fmm_clear_all_mem(void);
|
||||
void clear_process_doorbells(void);
|
||||
#endif
|
||||
|
||||
@@ -36,20 +36,39 @@
|
||||
static const char kfd_device_name[] = "/dev/kfd";
|
||||
static const char tmp_file[] = "/var/lock/.amd_hsa_thunk_lock";
|
||||
int amd_hsa_thunk_lock_fd = 0;
|
||||
static pid_t parent_pid = -1;
|
||||
|
||||
|
||||
static bool is_forked_child(void)
|
||||
{
|
||||
static pid_t open_pid = -1;
|
||||
pid_t my_pid = getpid();
|
||||
pid_t cur_pid = getpid();
|
||||
|
||||
if (open_pid == -1 || open_pid != my_pid) {
|
||||
open_pid = my_pid;
|
||||
return true;
|
||||
if (parent_pid == -1) {
|
||||
parent_pid = cur_pid;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parent_pid != cur_pid)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Call this from the child process after fork. This will clear all
|
||||
* data that is duplicated from the parent process, that is not valid
|
||||
* in the child.
|
||||
* The topology information is duplicated from the parent is valid
|
||||
* in the child process so it is not cleared
|
||||
*/
|
||||
static void clear_after_fork(void)
|
||||
{
|
||||
clear_process_doorbells();
|
||||
clear_events_page();
|
||||
fmm_clear_all_mem();
|
||||
destroy_device_debugging_memory();
|
||||
kfd_open_count = 0;
|
||||
}
|
||||
|
||||
HSAKMT_STATUS
|
||||
HSAKMTAPI
|
||||
hsaKmtOpenKFD(void)
|
||||
@@ -65,7 +84,7 @@ hsaKmtOpenKFD(void)
|
||||
* belong to the parent
|
||||
*/
|
||||
if (is_forked_child())
|
||||
kfd_open_count = 0;
|
||||
clear_after_fork();
|
||||
|
||||
if (kfd_open_count == 0)
|
||||
{
|
||||
|
||||
@@ -257,6 +257,29 @@ void destroy_process_doorbells(void)
|
||||
num_doorbells = 0;
|
||||
}
|
||||
|
||||
/* This is a special funcion that should be called only from the child process
|
||||
* after a fork(). This will clear doorbells duplicated from the parent.
|
||||
*/
|
||||
void clear_process_doorbells(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!doorbells)
|
||||
return;
|
||||
|
||||
for (i = 0; i < num_doorbells; i++) {
|
||||
if (doorbells[i].need_mmap)
|
||||
continue;
|
||||
|
||||
if (!use_gpuvm_doorbell(get_device_id_by_node(i)))
|
||||
munmap(doorbells[i].doorbells, DOORBELLS_PAGE_SIZE);
|
||||
}
|
||||
|
||||
free(doorbells);
|
||||
doorbells = NULL;
|
||||
num_doorbells = 0;
|
||||
}
|
||||
|
||||
static HSAKMT_STATUS map_doorbell_apu(HSAuint32 NodeId, HSAuint32 gpu_id,
|
||||
HSAuint64 doorbell_offset)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user