| 52 | } |
| 53 | |
| 54 | CudaKernelCommand::CudaKernelCommand(CUfunction func, void **params, void **extra, bool deep_copy) |
| 55 | : CudaCommand(preempt::kCommandPropertyDeactivatable) |
| 56 | // cuXtraKernelGetFunction() will convert func to CUfunction if func is a CUkernel. |
| 57 | , kFunc(func), kFuncHandle(cuXtraKernelGetFunction((CUkernel)func)) |
| 58 | , params_(params), extra_(extra) |
| 59 | { |
| 60 | if (!deep_copy) return; |
| 61 | |
| 62 | param_cnt_ = cuXtraGetParamCount(kFuncHandle); |
| 63 | /// @FIXME: even if param_cnt_ == 0, params or extra can be non-nullptr. |
| 64 | if (param_cnt_ == 0) return; |
| 65 | if (params == nullptr && extra == nullptr) { |
| 66 | XWARN("params and extra of kernel (%p) are both nullptr", func); |
| 67 | return; |
| 68 | } |
| 69 | if (params != nullptr && extra != nullptr) { |
| 70 | XWARN("illegally using both params (%p) and extra (%p) of kernel %p", params, extra, func); |
| 71 | return; |
| 72 | } |
| 73 | |
| 74 | deep_copy_ = true; |
| 75 | params_ = (void **)malloc(param_cnt_ * sizeof(void *)); |
| 76 | |
| 77 | if (params != nullptr) { |
| 78 | // Allocate a continuous buffer for all of the params |
| 79 | // buffer size = last param offset + last param size |
| 80 | size_t last_offset, last_size; |
| 81 | cuXtraGetParamInfo(kFuncHandle, param_cnt_ - 1, &last_offset, &last_size, nullptr); |
| 82 | size_t buffer_size = last_offset + last_size; |
| 83 | param_data_ = (char *)malloc(buffer_size); |
| 84 | |
| 85 | for (size_t i = 0; i < param_cnt_; ++i) { |
| 86 | size_t offset, size; |
| 87 | cuXtraGetParamInfo(kFuncHandle, i, &offset, &size, nullptr); |
| 88 | params_[i] = (void*)¶m_data_[offset]; |
| 89 | memcpy(params_[i], params[i], size); |
| 90 | } |
| 91 | } else if (extra != nullptr) { |
| 92 | // Get extra buffer and its size from extra map. |
| 93 | void *extra_buffer = nullptr; |
| 94 | cuXtraGetExtraBuffer(extra, &extra_buffer, &extra_buffer_size_); |
| 95 | // We have checked param_cnt_ > 0. |
| 96 | XASSERT(extra_buffer != nullptr && extra_buffer_size_ > 0, |
| 97 | "invalid extra buffer (%p) and size (%zu)", extra_buffer, extra_buffer_size_); |
| 98 | |
| 99 | // Deep-copy extra buffer to extra_data_. |
| 100 | extra_data_ = (char *)malloc(extra_buffer_size_); |
| 101 | memcpy(extra_data_, extra_buffer, extra_buffer_size_); |
| 102 | |
| 103 | // Set extra map. |
| 104 | extra_ = (void **)malloc(5 * sizeof(void *)); |
| 105 | extra_[0] = CU_LAUNCH_PARAM_BUFFER_POINTER; |
| 106 | extra_[1] = extra_data_; |
| 107 | extra_[2] = CU_LAUNCH_PARAM_BUFFER_SIZE; |
| 108 | extra_[3] = (void *)&extra_buffer_size_; |
| 109 | extra_[4] = CU_LAUNCH_PARAM_END; |
| 110 | |
| 111 | // Set params_ to point to extra_data_. |
nothing calls this directly
no outgoing calls
no test coverage detected