1d0b31295SJon Chesterfield /*===--------------------------------------------------------------------------
2d0b31295SJon Chesterfield  *              ATMI (Asynchronous Task and Memory Interface)
3d0b31295SJon Chesterfield  *
4d0b31295SJon Chesterfield  * This file is distributed under the MIT License. See LICENSE.txt for details.
5d0b31295SJon Chesterfield  *===------------------------------------------------------------------------*/
6d0b31295SJon Chesterfield #include "atmi_runtime.h"
7d0b31295SJon Chesterfield #include "internal.h"
8d0b31295SJon Chesterfield #include "machine.h"
9d0b31295SJon Chesterfield #include "rt.h"
10d0b31295SJon Chesterfield #include <cassert>
11d0b31295SJon Chesterfield #include <hsa.h>
12d0b31295SJon Chesterfield #include <hsa_ext_amd.h>
13d0b31295SJon Chesterfield #include <iostream>
14d0b31295SJon Chesterfield #include <stdio.h>
15d0b31295SJon Chesterfield #include <string.h>
16d0b31295SJon Chesterfield #include <thread>
17d0b31295SJon Chesterfield #include <vector>
18d0b31295SJon Chesterfield 
19d0b31295SJon Chesterfield using core::TaskImpl;
20d0b31295SJon Chesterfield extern ATLMachine g_atl_machine;
21d0b31295SJon Chesterfield 
22d0b31295SJon Chesterfield namespace core {
23d0b31295SJon Chesterfield void allow_access_to_all_gpu_agents(void *ptr);
24d0b31295SJon Chesterfield 
25d0b31295SJon Chesterfield const char *getPlaceStr(atmi_devtype_t type) {
26d0b31295SJon Chesterfield   switch (type) {
27d0b31295SJon Chesterfield   case ATMI_DEVTYPE_CPU:
28d0b31295SJon Chesterfield     return "CPU";
29d0b31295SJon Chesterfield   case ATMI_DEVTYPE_GPU:
30d0b31295SJon Chesterfield     return "GPU";
31d0b31295SJon Chesterfield   default:
32d0b31295SJon Chesterfield     return NULL;
33d0b31295SJon Chesterfield   }
34d0b31295SJon Chesterfield }
35d0b31295SJon Chesterfield 
36d0b31295SJon Chesterfield ATLProcessor &get_processor_by_mem_place(atmi_mem_place_t place) {
37d0b31295SJon Chesterfield   int dev_id = place.dev_id;
38d0b31295SJon Chesterfield   switch (place.dev_type) {
39d0b31295SJon Chesterfield   case ATMI_DEVTYPE_CPU:
40d0b31295SJon Chesterfield     return g_atl_machine.processors<ATLCPUProcessor>()[dev_id];
41d0b31295SJon Chesterfield   case ATMI_DEVTYPE_GPU:
42d0b31295SJon Chesterfield     return g_atl_machine.processors<ATLGPUProcessor>()[dev_id];
43d0b31295SJon Chesterfield   }
44d0b31295SJon Chesterfield }
45d0b31295SJon Chesterfield 
46d0b31295SJon Chesterfield hsa_amd_memory_pool_t get_memory_pool_by_mem_place(atmi_mem_place_t place) {
47d0b31295SJon Chesterfield   ATLProcessor &proc = get_processor_by_mem_place(place);
48d0b31295SJon Chesterfield   return get_memory_pool(proc, place.mem_id);
49d0b31295SJon Chesterfield }
50d0b31295SJon Chesterfield 
51d0b31295SJon Chesterfield void register_allocation(void *ptr, size_t size, atmi_mem_place_t place) {
52d0b31295SJon Chesterfield   if (place.dev_type == ATMI_DEVTYPE_CPU)
53d0b31295SJon Chesterfield     allow_access_to_all_gpu_agents(ptr);
54d0b31295SJon Chesterfield   // TODO(ashwinma): what if one GPU wants to access another GPU?
55d0b31295SJon Chesterfield }
56d0b31295SJon Chesterfield 
57d0b31295SJon Chesterfield atmi_status_t Runtime::Malloc(void **ptr, size_t size, atmi_mem_place_t place) {
58d0b31295SJon Chesterfield   atmi_status_t ret = ATMI_STATUS_SUCCESS;
59d0b31295SJon Chesterfield   hsa_amd_memory_pool_t pool = get_memory_pool_by_mem_place(place);
60d0b31295SJon Chesterfield   hsa_status_t err = hsa_amd_memory_pool_allocate(pool, size, 0, ptr);
61d0b31295SJon Chesterfield   ErrorCheck(atmi_malloc, err);
62d0b31295SJon Chesterfield   DEBUG_PRINT("Malloced [%s %d] %p\n",
63d0b31295SJon Chesterfield               place.dev_type == ATMI_DEVTYPE_CPU ? "CPU" : "GPU", place.dev_id,
64d0b31295SJon Chesterfield               *ptr);
65d0b31295SJon Chesterfield   if (err != HSA_STATUS_SUCCESS)
66d0b31295SJon Chesterfield     ret = ATMI_STATUS_ERROR;
67d0b31295SJon Chesterfield 
68d0b31295SJon Chesterfield   register_allocation(*ptr, size, place);
69d0b31295SJon Chesterfield 
70d0b31295SJon Chesterfield   return ret;
71d0b31295SJon Chesterfield }
72d0b31295SJon Chesterfield 
73d0b31295SJon Chesterfield atmi_status_t Runtime::Memfree(void *ptr) {
74d0b31295SJon Chesterfield   atmi_status_t ret = ATMI_STATUS_SUCCESS;
75d0b31295SJon Chesterfield   hsa_status_t err;
76d0b31295SJon Chesterfield   err = hsa_amd_memory_pool_free(ptr);
77d0b31295SJon Chesterfield   ErrorCheck(atmi_free, err);
78d0b31295SJon Chesterfield   DEBUG_PRINT("Freed %p\n", ptr);
79d0b31295SJon Chesterfield 
80*55dc1235SJonChesterfield   if (err != HSA_STATUS_SUCCESS)
81d0b31295SJon Chesterfield     ret = ATMI_STATUS_ERROR;
82d0b31295SJon Chesterfield   return ret;
83d0b31295SJon Chesterfield }
84d0b31295SJon Chesterfield 
85d0b31295SJon Chesterfield } // namespace core
86