@@ -22,7 +22,7 @@ static const __SYCL_CONSTANT__ char __tsan_print_generic_to[] =
22
22
" [kernel] %p(4) - %p(%d)\n " ;
23
23
24
24
static const __SYCL_CONSTANT__ char __tsan_print_raw_shadow[] =
25
- " [kernel] %p(%d) -> %p: {%x, %x, %x, %x }\n " ;
25
+ " [kernel] %p(%d) -> %p: {%x, %x}\n " ;
26
26
27
27
static const __SYCL_CONSTANT__ char __tsan_print_shadow_value[] =
28
28
" [kernel] %p(%d) : {size: %d, access: %x, sid: %d, clock: %d, is_write: "
@@ -90,26 +90,36 @@ inline __SYCL_GLOBAL__ RawShadow *MemToShadow_PVC(uptr addr, uint32_t as) {
90
90
ConvertGenericPointer (addr, as);
91
91
}
92
92
93
- if (as != ADDRESS_SPACE_GLOBAL)
94
- return nullptr ;
95
-
96
93
addr = RoundDownTo (addr, kShadowCell );
97
94
98
- if (addr & 0xff00'0000'0000'0000ULL ) {
99
- // device usm
100
- return addr < TsanLaunchInfo->GlobalShadowOffset
101
- ? reinterpret_cast <__SYCL_GLOBAL__ RawShadow *>(
102
- addr + (TsanLaunchInfo->GlobalShadowOffset +
103
- 0x200'0000'0000ULL - 0xff00'0000'0000'0000ULL ))
104
- : reinterpret_cast <__SYCL_GLOBAL__ RawShadow *>(
105
- addr - (0xff00'ffff'ffff'ffffULL -
106
- TsanLaunchInfo->GlobalShadowOffsetEnd + 1 ));
107
- } else {
108
- // host & shared usm
109
- return reinterpret_cast <__SYCL_GLOBAL__ RawShadow *>(
110
- (addr & 0xffffffffffULL ) + TsanLaunchInfo->GlobalShadowOffset +
111
- ((addr & 0x800000000000ULL ) >> 7 ));
95
+ if (as == ADDRESS_SPACE_GLOBAL) {
96
+ if (addr & 0xff00'0000'0000'0000ULL ) {
97
+ // device usm
98
+ return addr < TsanLaunchInfo->GlobalShadowOffset
99
+ ? reinterpret_cast <__SYCL_GLOBAL__ RawShadow *>(
100
+ addr + (TsanLaunchInfo->GlobalShadowOffset +
101
+ 0x200'0000'0000ULL - 0xff00'0000'0000'0000ULL ))
102
+ : reinterpret_cast <__SYCL_GLOBAL__ RawShadow *>(
103
+ addr - (0xff00'ffff'ffff'ffffULL -
104
+ TsanLaunchInfo->GlobalShadowOffsetEnd + 1 ));
105
+ } else {
106
+ // host & shared usm
107
+ return reinterpret_cast <__SYCL_GLOBAL__ RawShadow *>(
108
+ (addr & 0xffffffffffULL ) + TsanLaunchInfo->GlobalShadowOffset +
109
+ ((addr & 0x800000000000ULL ) >> 7 ));
110
+ }
111
+ } else if (as == ADDRESS_SPACE_LOCAL) {
112
+ const auto shadow_offset = TsanLaunchInfo->LocalShadowOffset ;
113
+ if (shadow_offset != 0 ) {
114
+ // The size of SLM is 128KB on PVC
115
+ constexpr unsigned SLM_SIZE = 128 * 1024 ;
116
+ const size_t wid = WorkGroupLinearId ();
117
+ return reinterpret_cast <__SYCL_GLOBAL__ RawShadow *>(
118
+ shadow_offset + (wid * SLM_SIZE) + (addr & (SLM_SIZE - 1 )));
119
+ }
112
120
}
121
+
122
+ return nullptr ;
113
123
}
114
124
115
125
inline __SYCL_GLOBAL__ RawShadow *MemToShadow (uptr addr, uint32_t as) {
@@ -151,7 +161,7 @@ inline void StoreShadow(__SYCL_GLOBAL__ RawShadow *p, RawShadow s) {
151
161
}
152
162
153
163
inline void DoReportRace (__SYCL_GLOBAL__ RawShadow *s, AccessType type,
154
- uptr addr, uint32_t size,
164
+ uptr addr, uint32_t size, uint32_t as,
155
165
const char __SYCL_CONSTANT__ *file, uint32_t line,
156
166
const char __SYCL_CONSTANT__ *func) {
157
167
// This prevents trapping on this address in future.
@@ -179,8 +189,13 @@ inline void DoReportRace(__SYCL_GLOBAL__ RawShadow *s, AccessType type,
179
189
auto &SanitizerReport =
180
190
TsanLaunchInfo->Report [TsanLaunchInfo->RecordedReportCount ++];
181
191
192
+ if (as == ADDRESS_SPACE_GENERIC) {
193
+ ConvertGenericPointer (addr, as);
194
+ }
195
+
182
196
SanitizerReport.Address = addr;
183
- SanitizerReport.Type = type;
197
+ SanitizerReport.Type =
198
+ type | (as == ADDRESS_SPACE_LOCAL ? kAccessLocal : 0 );
184
199
SanitizerReport.AccessSize = size;
185
200
186
201
int FileLength = 0 ;
@@ -224,7 +239,7 @@ inline void DoReportRace(__SYCL_GLOBAL__ RawShadow *s, AccessType type,
224
239
}
225
240
226
241
inline bool CheckRace (__SYCL_GLOBAL__ RawShadow *s, Shadow cur, AccessType type,
227
- uptr addr, uint32_t size,
242
+ uptr addr, uint32_t size, uint32_t as,
228
243
const char __SYCL_CONSTANT__ *file, uint32_t line,
229
244
const char __SYCL_CONSTANT__ *func) {
230
245
bool stored = false ;
@@ -258,7 +273,7 @@ inline bool CheckRace(__SYCL_GLOBAL__ RawShadow *s, Shadow cur, AccessType type,
258
273
if (TsanLaunchInfo->Clock [cur.sid ()].clk_ [old.sid ()] >= old.clock ())
259
274
continue ;
260
275
261
- DoReportRace (s, type, addr, size, file, line, func);
276
+ DoReportRace (s, type, addr, size, as, file, line, func);
262
277
return true ;
263
278
}
264
279
@@ -301,17 +316,17 @@ inline bool ContainsSameAccess(__SYCL_GLOBAL__ RawShadow *s, Shadow cur,
301
316
return ; \
302
317
Sid sid = GetCurrentSid (); \
303
318
uint16_t current_clock = IncrementEpoch (sid) + 1 ; \
304
- TSAN_DEBUG (__spirv_ocl_printf ( \
305
- __tsan_print_raw_shadow, ( void *)addr, as, (void *)shadow_mem, \
306
- shadow_mem[ 0 ], shadow_mem[ 1 ], shadow_mem[ 2 ], shadow_mem[3 ])); \
319
+ TSAN_DEBUG (__spirv_ocl_printf (__tsan_print_raw_shadow, ( void *)addr, as, \
320
+ (void *)shadow_mem, shadow_mem[ 0 ], \
321
+ shadow_mem[1 ])); \
307
322
AccessType type = is_write ? kAccessWrite : kAccessRead ; \
308
323
Shadow cur (addr, size, current_clock, sid, type); \
309
324
TSAN_DEBUG (__spirv_ocl_printf (__tsan_print_shadow_value, (void *)addr, as, \
310
325
size, cur.access (), cur.sid (), cur.clock (), \
311
326
is_write)); \
312
327
if (ContainsSameAccess (shadow_mem, cur, type)) \
313
328
return ; \
314
- CheckRace (shadow_mem, cur, type, addr, size, file, line, func); \
329
+ CheckRace (shadow_mem, cur, type, addr, size, as, file, line, func); \
315
330
}
316
331
317
332
TSAN_CHECK (read, false , 1 )
@@ -349,16 +364,16 @@ __tsan_read16(uptr addr, uint32_t as, const char __SYCL_CONSTANT__ *file,
349
364
AccessType type = is_write ? kAccessWrite : kAccessRead ; \
350
365
uptr size1 = Min (size, RoundUpTo (addr + 1 , kShadowCell ) - addr); \
351
366
{ \
352
- TSAN_DEBUG (__spirv_ocl_printf ( \
353
- __tsan_print_raw_shadow, ( void *)addr, as, (void *)shadow_mem, \
354
- shadow_mem[ 0 ], shadow_mem[ 1 ], shadow_mem[ 2 ], shadow_mem[3 ])); \
367
+ TSAN_DEBUG (__spirv_ocl_printf (__tsan_print_raw_shadow, ( void *)addr, as, \
368
+ (void *)shadow_mem, shadow_mem[ 0 ], \
369
+ shadow_mem[1 ])); \
355
370
Shadow cur (addr, size1, current_clock, sid, type); \
356
371
TSAN_DEBUG (__spirv_ocl_printf (__tsan_print_shadow_value, (void *)addr, \
357
372
as, size1, cur.access (), cur.sid (), \
358
373
cur.clock (), is_write)); \
359
374
if (ContainsSameAccess (shadow_mem, cur, type)) \
360
375
goto SECOND; \
361
- if (CheckRace (shadow_mem, cur, type, addr, size1, file, line, func)) \
376
+ if (CheckRace (shadow_mem, cur, type, addr, size1, as, file, line, func)) \
362
377
return ; \
363
378
} \
364
379
SECOND: \
@@ -367,17 +382,17 @@ __tsan_read16(uptr addr, uint32_t as, const char __SYCL_CONSTANT__ *file,
367
382
return ; \
368
383
shadow_mem += kShadowCnt ; \
369
384
{ \
370
- TSAN_DEBUG ( \
371
- __spirv_ocl_printf (__tsan_print_raw_shadow, (void *)(addr + size1), \
372
- as, (void *)shadow_mem, shadow_mem[0 ], \
373
- shadow_mem[1 ], shadow_mem[2 ], shadow_mem[3 ])); \
385
+ TSAN_DEBUG (__spirv_ocl_printf ( \
386
+ __tsan_print_raw_shadow, (void *)(addr + size1), as, \
387
+ (void *)shadow_mem, shadow_mem[0 ], shadow_mem[1 ])); \
374
388
Shadow cur (0 , size2, current_clock, sid, type); \
375
389
TSAN_DEBUG (__spirv_ocl_printf ( \
376
390
__tsan_print_shadow_value, (void *)(addr + size1), as, size2, \
377
391
cur.access (), cur.sid (), cur.clock (), is_write)); \
378
392
if (ContainsSameAccess (shadow_mem, cur, type)) \
379
393
return ; \
380
- CheckRace (shadow_mem, cur, type, addr + size1, size2, file, line, func); \
394
+ CheckRace (shadow_mem, cur, type, addr + size1, size2, as, file, line, \
395
+ func); \
381
396
} \
382
397
}
383
398
@@ -420,7 +435,7 @@ static inline void __tsan_cleanup_private_cpu_impl(uptr addr, uint32_t size) {
420
435
}
421
436
}
422
437
423
- DEVICE_EXTERN_C_NOINLINE void __tsan_cleanup_private (uptr addr, uint32_t size) {
438
+ DEVICE_EXTERN_C_NOINLINE void __tsan_cleanup_private (uptr addr, size_t size) {
424
439
#if defined(__LIBDEVICE_CPU__)
425
440
__tsan_cleanup_private_cpu_impl (addr, size);
426
441
#elif defined(__LIBDEVICE_PVC__)
@@ -433,6 +448,55 @@ DEVICE_EXTERN_C_NOINLINE void __tsan_cleanup_private(uptr addr, uint32_t size) {
433
448
#endif
434
449
}
435
450
451
+ static __SYCL_CONSTANT__ const char __tsan_print_cleanup_local[] =
452
+ " [kernel] cleanup shadow (%p ~ %p) for local %p\n " ;
453
+
454
+ DEVICE_EXTERN_C_NOINLINE void __tsan_cleanup_static_local (uptr addr,
455
+ size_t size) {
456
+ // Update shadow memory of local memory only on first work-item
457
+ if (__spirv_LocalInvocationId_x () + __spirv_LocalInvocationId_y () +
458
+ __spirv_LocalInvocationId_z () ==
459
+ 0 ) {
460
+ if (TsanLaunchInfo->LocalShadowOffset == 0 )
461
+ return ;
462
+
463
+ addr = RoundDownTo (addr, kShadowCell );
464
+ size = RoundUpTo (size, kShadowCell );
465
+
466
+ RawShadow *Begin = MemToShadow (addr, ADDRESS_SPACE_LOCAL);
467
+ for (uptr i = 0 ; i < size / kShadowCell * kShadowCnt ; i++)
468
+ Begin[i] = 0 ;
469
+
470
+ TSAN_DEBUG (__spirv_ocl_printf (
471
+ __tsan_print_cleanup_local, addr, Begin,
472
+ (uptr)Begin + size / kShadowCell * kShadowCnt * kShadowSize - 1 ));
473
+ }
474
+ }
475
+
476
+ static __SYCL_CONSTANT__ const char __tsan_print_report_arg_count_incorrect[] =
477
+ " [kernel] ERROR: The number of local args is incorrect, expect %d, actual "
478
+ " %d\n " ;
479
+
480
+ DEVICE_EXTERN_C_NOINLINE void __tsan_cleanup_dynamic_local (uptr ptr,
481
+ uint32_t num_args) {
482
+ if (!TsanLaunchInfo->LocalShadowOffset )
483
+ return ;
484
+
485
+ if (num_args != TsanLaunchInfo->NumLocalArgs ) {
486
+ __spirv_ocl_printf (__tsan_print_report_arg_count_incorrect, num_args,
487
+ TsanLaunchInfo->NumLocalArgs );
488
+ return ;
489
+ }
490
+
491
+ uptr *args = (uptr *)ptr;
492
+
493
+ for (uint32_t i = 0 ; i < num_args; ++i) {
494
+ auto *local_arg = &TsanLaunchInfo->LocalArgs [i];
495
+
496
+ __tsan_cleanup_static_local (args[i], local_arg->Size );
497
+ }
498
+ }
499
+
436
500
DEVICE_EXTERN_C_INLINE void __tsan_device_barrier () {
437
501
Sid sid = GetCurrentSid ();
438
502
0 commit comments