Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

atomic_add impl report error by ThreadSanitizer #28

Open
moonlightsh opened this issue Nov 27, 2023 · 0 comments
Open

atomic_add impl report error by ThreadSanitizer #28

moonlightsh opened this issue Nov 27, 2023 · 0 comments

Comments

@moonlightsh
Copy link

hello,
I learn a lot from you project,
When I write a multi-thread program and test.
I use tsan to check data race, reports error:

0x7b0c00000328
==================
WARNING: ThreadSanitizer: data race (pid=48322)
  Read of size 8 at 0x7b0c00000318 by thread T1:
    #0 sref mman.c:91 (a.out:x86_64+0x100002c47)
    #1 thr main.c:16 (a.out:x86_64+0x100002655)
old_count: 2
  Previous atomic write of size 8 at 0x7b0c00000318 by main thread:
    #0 sref mman.c:91 (a.out:x86_64+0x100002c95)
    #1 main main.c:31 (a.out:x86_64+0x1000027a6)
old_count: 2
  Location is heap block of size 48 at 0x7b0c00000300 allocated by main thread:
    #0 malloc <null>:188732607 (libclang_rt.tsan_osx_dynamic.dylib:x86_64h+0x55a7c)
    #1 smalloc_impl mman.c:163 (a.out:x86_64+0x10000349d)
    #2 smalloc mman.c:212 (a.out:x86_64+0x100003341)
    #3 main main.c:26 (a.out:x86_64+0x1000026ed)

  Thread T1 (tid=486984, running) created by main thread at:
    #0 pthread_create <null>:188732607 (libclang_rt.tsan_osx_dynamic.dylib:x86_64h+0x3155f)
    #1 main main.c:30 (a.out:x86_64+0x100002794)

there is a simple demo just for test:

#include <stdio.h>
#include <pthread.h>
#include <assert.h>
#include <csptr/smart_ptr.h>

struct T {
    int foo;
};

static void cleanupfunc(void *ptr, void *meta) {
    printf("cleanupfunc\n");
}

void *thr(void *p)
{
    sref(p);
    sfree(p);
    return NULL;
}

int main()
{
    pthread_t t1;
    pthread_t t2;
    pthread_t t3;
    smart struct T *p = shared_ptr(struct T, {}, cleanupfunc);
    
    sref(p);
    pthread_create(&t1, NULL, thr, p);
    sref(p);
    pthread_create(&t2, NULL, thr, p);
    sref(p);
    pthread_create(&t3, NULL, thr, p);
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    pthread_join(t3, NULL);
    sfree(p);
    sfree(p);
    sfree(p);
}

I check the code, found maybe the non-sync access for count ,

libcsptr/src/mman.c

Lines 43 to 52 in ac73451

static CSPTR_INLINE size_t atomic_add(volatile size_t *count, const size_t limit, const size_t val) {
size_t old_count, new_count;
do {
old_count = *count;
if (old_count == limit)
abort();
new_count = old_count + val;
} while (!__sync_bool_compare_and_swap(count, old_count, new_count));
return new_count;
}

But in think it not a real issue ,unless in x64. I got a way to avoid from abort of tsan, is it just make it happier?

static CSPTR_INLINE size_t atomic_add(volatile size_t *count, const size_t limit, const size_t val) {
    size_t old_count, new_count;
    do {
      old_count = __sync_fetch_and_add(count, 0);
      if (old_count == limit)
          abort();
      new_count = old_count + val;
    } while (!__sync_bool_compare_and_swap(count, old_count, new_count));
    return new_count;
}

also commit :
983932

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant