[Beignet] [PATCH] Fix the printf buffer size bug.
junyan.he at inbox.com
junyan.he at inbox.com
Sun Jan 11 21:55:22 PST 2015
From: Junyan He <junyan.he at linux.intel.com>
We can not know the accurate size of the printf buffer
size before run the kernel. Sometimes, especially when
the global work items size is huge, the output buffer
is not enough and the print message logic will cause the
segment fault.
We increase the printf buffer to 16M at most and add out
of range check to avoid crash.
Signed-off-by: Junyan He <junyan.he at linux.intel.com>
---
backend/src/backend/program.cpp | 5 +++--
backend/src/backend/program.h | 2 +-
backend/src/backend/program.hpp | 4 ++--
backend/src/ir/printf.cpp | 16 ++++++++++------
backend/src/ir/printf.hpp | 2 +-
src/cl_command_queue.c | 5 +++--
src/cl_command_queue_gen7.c | 2 +-
src/cl_driver.h | 2 +-
src/intel/intel_gpgpu.c | 4 +++-
9 files changed, 25 insertions(+), 17 deletions(-)
diff --git a/backend/src/backend/program.cpp b/backend/src/backend/program.cpp
index b22e4a6..38ce9c8 100644
--- a/backend/src/backend/program.cpp
+++ b/backend/src/backend/program.cpp
@@ -1068,12 +1068,13 @@ namespace gbe {
static void kernelOutputPrintf(void * printf_info, void* index_addr,
void* buf_addr, size_t global_wk_sz0,
- size_t global_wk_sz1, size_t global_wk_sz2)
+ size_t global_wk_sz1, size_t global_wk_sz2,
+ size_t output_sz)
{
if (printf_info == NULL) return;
ir::PrintfSet *ps = (ir::PrintfSet *)printf_info;
ps->outputPrintf(index_addr, buf_addr, global_wk_sz0,
- global_wk_sz1, global_wk_sz2);
+ global_wk_sz1, global_wk_sz2, output_sz);
}
static void kernelGetCompileWorkGroupSize(gbe_kernel gbeKernel, size_t wg_size[3]) {
diff --git a/backend/src/backend/program.h b/backend/src/backend/program.h
index 6acc010..dc5662f 100644
--- a/backend/src/backend/program.h
+++ b/backend/src/backend/program.h
@@ -157,7 +157,7 @@ typedef uint32_t (gbe_get_printf_sizeof_size_cb)(void* printf_info);
extern gbe_get_printf_sizeof_size_cb *gbe_get_printf_sizeof_size;
typedef void (gbe_output_printf_cb) (void* printf_info, void* index_addr, void* buf_addr,
- size_t global_wk_sz0, size_t global_wk_sz1, size_t global_wk_sz2);
+ size_t global_wk_sz0, size_t global_wk_sz1, size_t global_wk_sz2, size_t outbuf_sz);
extern gbe_output_printf_cb* gbe_output_printf;
/*! Create a new program from the given source code (zero terminated string) */
diff --git a/backend/src/backend/program.hpp b/backend/src/backend/program.hpp
index 66f90aa..cff2463 100644
--- a/backend/src/backend/program.hpp
+++ b/backend/src/backend/program.hpp
@@ -155,10 +155,10 @@ namespace gbe {
}
void outputPrintf(void* index_addr, void* buf_addr, size_t global_wk_sz0,
- size_t global_wk_sz1, size_t global_wk_sz2) {
+ size_t global_wk_sz1, size_t global_wk_sz2, size_t output_sz) {
if(printfSet)
printfSet->outputPrintf(index_addr, buf_addr, global_wk_sz0,
- global_wk_sz1, global_wk_sz2);
+ global_wk_sz1, global_wk_sz2, output_sz);
}
ir::FunctionArgument::InfoFromLLVM* getArgInfo(uint32_t id) const { return &args[id].info; }
diff --git a/backend/src/ir/printf.cpp b/backend/src/ir/printf.cpp
index 0e9f81c..fa108dc 100644
--- a/backend/src/ir/printf.cpp
+++ b/backend/src/ir/printf.cpp
@@ -105,16 +105,20 @@ namespace gbe
#define PRINT_SOMETHING(target_ty, conv) do { \
if (!vec_i) \
pf_str = pf_str + std::string(#conv); \
- printf(pf_str.c_str(), \
- ((target_ty *)((char *)buf_addr + sizeOfSize * global_wk_sz0 * global_wk_sz1 * global_wk_sz2 * n \
- + slot.state->out_buf_sizeof_offset * \
- global_wk_sz0 * global_wk_sz1 * global_wk_sz2)) \
- [(k*global_wk_sz0*global_wk_sz1 + j*global_wk_sz0 + i) * vec_num + vec_i]);\
+ char *ptr = ((char *)buf_addr + sizeOfSize * global_wk_sz0 * global_wk_sz1 * global_wk_sz2 * n \
+ + slot.state->out_buf_sizeof_offset * \
+ global_wk_sz0 * global_wk_sz1 * global_wk_sz2); \
+ target_ty* obj_ptr = ((target_ty *)ptr) + (k*global_wk_sz0*global_wk_sz1 + j*global_wk_sz0 + i) * vec_num + vec_i; \
+ if ((char *)obj_ptr + sizeof(target_ty) > (char *)buf_addr + output_sz) { \
+ printf("\n\n!!!The printf message is out of range because of the limited buffer, ignore.\n"); \
+ return; \
+ } \
+ printf(pf_str.c_str(), *obj_ptr); \
} while (0)
void PrintfSet::outputPrintf(void* index_addr, void* buf_addr, size_t global_wk_sz0,
- size_t global_wk_sz1, size_t global_wk_sz2)
+ size_t global_wk_sz1, size_t global_wk_sz2, size_t output_sz)
{
LockOutput lock;
size_t i, j, k;
diff --git a/backend/src/ir/printf.hpp b/backend/src/ir/printf.hpp
index cc1f8dc..f6c6bcf 100644
--- a/backend/src/ir/printf.hpp
+++ b/backend/src/ir/printf.hpp
@@ -253,7 +253,7 @@ namespace gbe
}
void outputPrintf(void* index_addr, void* buf_addr, size_t global_wk_sz0,
- size_t global_wk_sz1, size_t global_wk_sz2);
+ size_t global_wk_sz1, size_t global_wk_sz2, size_t output_sz);
private:
vector<PrintfFmt> fmts;
diff --git a/src/cl_command_queue.c b/src/cl_command_queue.c
index 6103909..89afa07 100644
--- a/src/cl_command_queue.c
+++ b/src/cl_command_queue.c
@@ -216,7 +216,8 @@ LOCAL void
cl_command_queue_flush_gpgpu(cl_command_queue queue, cl_gpgpu gpgpu)
{
size_t global_wk_sz[3];
- void* printf_info = cl_gpgpu_get_printf_info(gpgpu, global_wk_sz);
+ size_t outbuf_sz = 0;
+ void* printf_info = cl_gpgpu_get_printf_info(gpgpu, global_wk_sz, &outbuf_sz);
cl_gpgpu_flush(gpgpu);
@@ -227,7 +228,7 @@ cl_command_queue_flush_gpgpu(cl_command_queue queue, cl_gpgpu gpgpu)
buf_addr = cl_gpgpu_map_printf_buffer(gpgpu, 1);
interp_output_printf(printf_info, index_addr, buf_addr, global_wk_sz[0],
- global_wk_sz[1], global_wk_sz[2]);
+ global_wk_sz[1], global_wk_sz[2], outbuf_sz);
cl_gpgpu_unmap_printf_buffer(gpgpu, 0);
if (interp_get_printf_sizeof_size(printf_info))
diff --git a/src/cl_command_queue_gen7.c b/src/cl_command_queue_gen7.c
index 734267a..eec39b4 100644
--- a/src/cl_command_queue_gen7.c
+++ b/src/cl_command_queue_gen7.c
@@ -281,7 +281,7 @@ cl_bind_printf(cl_gpgpu gpgpu, cl_kernel ker, void* printf_info, int printf_num,
if (buf_size < 1*1024)
buf_size = 1*1024*1024;
else
- buf_size = 4*1024*1024; //at most.
+ buf_size = 16*1024*1024; //at most.
if (offset > 0) {
if (cl_gpgpu_set_printf_buffer(gpgpu, 1, buf_size, offset, interp_get_printf_buf_bti(printf_info)) != 0)
diff --git a/src/cl_driver.h b/src/cl_driver.h
index f13ebee..c88b9be 100644
--- a/src/cl_driver.h
+++ b/src/cl_driver.h
@@ -266,7 +266,7 @@ typedef int (cl_gpgpu_set_printf_info_cb)(cl_gpgpu, void *, size_t*);
extern cl_gpgpu_set_printf_info_cb *cl_gpgpu_set_printf_info;
/* Get the last printfset pointer */
-typedef void* (cl_gpgpu_get_printf_info_cb)(cl_gpgpu, size_t*);
+typedef void* (cl_gpgpu_get_printf_info_cb)(cl_gpgpu, size_t*, size_t*);
extern cl_gpgpu_get_printf_info_cb *cl_gpgpu_get_printf_info;
/* Will spawn all threads */
diff --git a/src/intel/intel_gpgpu.c b/src/intel/intel_gpgpu.c
index 1836bfd..e583433 100644
--- a/src/intel/intel_gpgpu.c
+++ b/src/intel/intel_gpgpu.c
@@ -1896,11 +1896,13 @@ intel_gpgpu_set_printf_info(intel_gpgpu_t *gpgpu, void* printf_info, size_t * gl
}
static void*
-intel_gpgpu_get_printf_info(intel_gpgpu_t *gpgpu, size_t * global_sz)
+intel_gpgpu_get_printf_info(intel_gpgpu_t *gpgpu, size_t * global_sz, size_t *outbuf_sz)
{
global_sz[0] = gpgpu->global_wk_sz[0];
global_sz[1] = gpgpu->global_wk_sz[1];
global_sz[2] = gpgpu->global_wk_sz[2];
+
+ *outbuf_sz = gpgpu->printf_b.bo->size;
return gpgpu->printf_info;
}
--
1.7.9.5
More information about the Beignet
mailing list