data race within ptr_ring code implementation
Clash Royale CLAN TAG#URR8PPP
I am implementing single-producer,single-consumer ptr_ring buffers. Are there really data races within this linux driver code ?
I asked this because ThreadSanitizer gives me error and my system crashes after I started the ptr_ring code implementation.
I have added locks to push_circ_queue(), pop_circ_queue() and free_circ_queue(). Why does data race still occur ?
Edit:
I think I got why I still have data race
I have two different instances of ptr_ring, for sending (chnl_send) and receiving (chnl_recv) purposes respectively.
push_circ_queue() and pop_circ_queue() for the same ptr_ring should not be executed concurrently by interupt handler (push) and the corresponding thread (pop)
how would I code the mutex lock code in this case ?
a mutex that makes push_circ_queue(ptr_ring A) and pop_circ_queue(ptr_ring A) cannot be executed concurrently
same for push_circ_queue(ptr_ring B) and pop_circ_queue(ptr_ring B)
but the problem got worse when push_circ_queue() is inside a interrupt handler
Any help ?
/*
* Filename: circ_ring.c
* Version: 1.0
* Description: A circular buffer using API from
* https://github.com/torvalds/linux/blob/master/include/linux/ptr_ring.h
*/
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/ptr_ring.h>
#include "circ_ring.h"
//#include <assert.h>
#define DEBUG 1
#ifdef DEBUG
#define DEBUG_MSG(...) printk(__VA_ARGS__)
#else
#define DEBUG_MSG(...)
#endif
struct mutex lock_push;
struct mutex lock_pop;
struct mutex lock_cleanup;
struct ptr_ring * init_circ_queue(int len)
struct ptr_ring * q;
q = kzalloc(sizeof(struct ptr_ring), GFP_KERNEL);
if (q == NULL)
DEBUG_MSG(KERN_ERR "Not enough memory to allocate ptr_ring");
return NULL;
// creates an array of length 'len' where each array location can store a struct * item
if(ptr_ring_init(q, len, GFP_KERNEL) != 0)
DEBUG_MSG(KERN_ERR "Not enough memory to allocate ptr_ring array");
return NULL;
return q;
inline int push_circ_queue(struct ptr_ring * buffer, struct item * item_push)
mutex_lock(&lock_push);
/* insert one item into the buffer */
if(ptr_ring_produce_any(buffer, item_push) == 0) // operation is successful
DEBUG_MSG(KERN_INFO "Successfully pushed val1 = %u and val2 = %un", item_push->val1, item_push->val2);
mutex_unlock(&lock_push);
return 0;
else
DEBUG_MSG(KERN_INFO "full, not enough buffer spacen");
mutex_unlock(&lock_push);
return 1;
inline int pop_circ_queue(struct ptr_ring * buffer, struct item * item_pop)
mutex_lock(&lock_pop);
struct item * item_temp;
/* extract one item struct containing two unsigned integers from the buffer */
item_temp = (struct item *)ptr_ring_consume_any(buffer);
if(item_temp) // (!= NULL)
item_pop->val1 = item_temp->val1;
item_pop->val2 = item_temp->val2;
// val1 will never be zero since the event number starts from 1 (so, val1 in push_circ_queue() will not be zero,
// same case after pop_circ_queue()), and 0 is only possible during initialization, not during pop_circ_queue()
//assert(item_pop->val1 != 0);
DEBUG_MSG(KERN_INFO "Before pop, head = %u , tail = %un", buffer->consumer_head, buffer->consumer_tail);
DEBUG_MSG(KERN_INFO "val1 = %u , val2 = %un", item_pop->val1, item_pop->val2);
DEBUG_MSG(KERN_INFO "After pop, head = %u , tail = %un", buffer->consumer_head, buffer->consumer_tail);
mutex_unlock(&lock_pop);
return 0;
else
//DEBUG_MSG(KERN_INFO "empty, nothing to pop from the ringn");
mutex_unlock(&lock_pop);
return 1;
void free_circ_queue(struct ptr_ring * q)
mutex_lock(&lock_cleanup);
ptr_ring_cleanup(q, NULL);
mutex_unlock(&lock_cleanup);
multithreading kernel buffer driver address-sanitizer
migrated from unix.stackexchange.com yesterday
This question came from our site for users of Linux, FreeBSD and other Un*x-like operating systems.
add a comment |
I am implementing single-producer,single-consumer ptr_ring buffers. Are there really data races within this linux driver code ?
I asked this because ThreadSanitizer gives me error and my system crashes after I started the ptr_ring code implementation.
I have added locks to push_circ_queue(), pop_circ_queue() and free_circ_queue(). Why does data race still occur ?
Edit:
I think I got why I still have data race
I have two different instances of ptr_ring, for sending (chnl_send) and receiving (chnl_recv) purposes respectively.
push_circ_queue() and pop_circ_queue() for the same ptr_ring should not be executed concurrently by interupt handler (push) and the corresponding thread (pop)
how would I code the mutex lock code in this case ?
a mutex that makes push_circ_queue(ptr_ring A) and pop_circ_queue(ptr_ring A) cannot be executed concurrently
same for push_circ_queue(ptr_ring B) and pop_circ_queue(ptr_ring B)
but the problem got worse when push_circ_queue() is inside a interrupt handler
Any help ?
/*
* Filename: circ_ring.c
* Version: 1.0
* Description: A circular buffer using API from
* https://github.com/torvalds/linux/blob/master/include/linux/ptr_ring.h
*/
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/ptr_ring.h>
#include "circ_ring.h"
//#include <assert.h>
#define DEBUG 1
#ifdef DEBUG
#define DEBUG_MSG(...) printk(__VA_ARGS__)
#else
#define DEBUG_MSG(...)
#endif
struct mutex lock_push;
struct mutex lock_pop;
struct mutex lock_cleanup;
struct ptr_ring * init_circ_queue(int len)
struct ptr_ring * q;
q = kzalloc(sizeof(struct ptr_ring), GFP_KERNEL);
if (q == NULL)
DEBUG_MSG(KERN_ERR "Not enough memory to allocate ptr_ring");
return NULL;
// creates an array of length 'len' where each array location can store a struct * item
if(ptr_ring_init(q, len, GFP_KERNEL) != 0)
DEBUG_MSG(KERN_ERR "Not enough memory to allocate ptr_ring array");
return NULL;
return q;
inline int push_circ_queue(struct ptr_ring * buffer, struct item * item_push)
mutex_lock(&lock_push);
/* insert one item into the buffer */
if(ptr_ring_produce_any(buffer, item_push) == 0) // operation is successful
DEBUG_MSG(KERN_INFO "Successfully pushed val1 = %u and val2 = %un", item_push->val1, item_push->val2);
mutex_unlock(&lock_push);
return 0;
else
DEBUG_MSG(KERN_INFO "full, not enough buffer spacen");
mutex_unlock(&lock_push);
return 1;
inline int pop_circ_queue(struct ptr_ring * buffer, struct item * item_pop)
mutex_lock(&lock_pop);
struct item * item_temp;
/* extract one item struct containing two unsigned integers from the buffer */
item_temp = (struct item *)ptr_ring_consume_any(buffer);
if(item_temp) // (!= NULL)
item_pop->val1 = item_temp->val1;
item_pop->val2 = item_temp->val2;
// val1 will never be zero since the event number starts from 1 (so, val1 in push_circ_queue() will not be zero,
// same case after pop_circ_queue()), and 0 is only possible during initialization, not during pop_circ_queue()
//assert(item_pop->val1 != 0);
DEBUG_MSG(KERN_INFO "Before pop, head = %u , tail = %un", buffer->consumer_head, buffer->consumer_tail);
DEBUG_MSG(KERN_INFO "val1 = %u , val2 = %un", item_pop->val1, item_pop->val2);
DEBUG_MSG(KERN_INFO "After pop, head = %u , tail = %un", buffer->consumer_head, buffer->consumer_tail);
mutex_unlock(&lock_pop);
return 0;
else
//DEBUG_MSG(KERN_INFO "empty, nothing to pop from the ringn");
mutex_unlock(&lock_pop);
return 1;
void free_circ_queue(struct ptr_ring * q)
mutex_lock(&lock_cleanup);
ptr_ring_cleanup(q, NULL);
mutex_unlock(&lock_cleanup);
multithreading kernel buffer driver address-sanitizer
migrated from unix.stackexchange.com yesterday
This question came from our site for users of Linux, FreeBSD and other Un*x-like operating systems.
add a comment |
I am implementing single-producer,single-consumer ptr_ring buffers. Are there really data races within this linux driver code ?
I asked this because ThreadSanitizer gives me error and my system crashes after I started the ptr_ring code implementation.
I have added locks to push_circ_queue(), pop_circ_queue() and free_circ_queue(). Why does data race still occur ?
Edit:
I think I got why I still have data race
I have two different instances of ptr_ring, for sending (chnl_send) and receiving (chnl_recv) purposes respectively.
push_circ_queue() and pop_circ_queue() for the same ptr_ring should not be executed concurrently by interupt handler (push) and the corresponding thread (pop)
how would I code the mutex lock code in this case ?
a mutex that makes push_circ_queue(ptr_ring A) and pop_circ_queue(ptr_ring A) cannot be executed concurrently
same for push_circ_queue(ptr_ring B) and pop_circ_queue(ptr_ring B)
but the problem got worse when push_circ_queue() is inside a interrupt handler
Any help ?
/*
* Filename: circ_ring.c
* Version: 1.0
* Description: A circular buffer using API from
* https://github.com/torvalds/linux/blob/master/include/linux/ptr_ring.h
*/
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/ptr_ring.h>
#include "circ_ring.h"
//#include <assert.h>
#define DEBUG 1
#ifdef DEBUG
#define DEBUG_MSG(...) printk(__VA_ARGS__)
#else
#define DEBUG_MSG(...)
#endif
struct mutex lock_push;
struct mutex lock_pop;
struct mutex lock_cleanup;
struct ptr_ring * init_circ_queue(int len)
struct ptr_ring * q;
q = kzalloc(sizeof(struct ptr_ring), GFP_KERNEL);
if (q == NULL)
DEBUG_MSG(KERN_ERR "Not enough memory to allocate ptr_ring");
return NULL;
// creates an array of length 'len' where each array location can store a struct * item
if(ptr_ring_init(q, len, GFP_KERNEL) != 0)
DEBUG_MSG(KERN_ERR "Not enough memory to allocate ptr_ring array");
return NULL;
return q;
inline int push_circ_queue(struct ptr_ring * buffer, struct item * item_push)
mutex_lock(&lock_push);
/* insert one item into the buffer */
if(ptr_ring_produce_any(buffer, item_push) == 0) // operation is successful
DEBUG_MSG(KERN_INFO "Successfully pushed val1 = %u and val2 = %un", item_push->val1, item_push->val2);
mutex_unlock(&lock_push);
return 0;
else
DEBUG_MSG(KERN_INFO "full, not enough buffer spacen");
mutex_unlock(&lock_push);
return 1;
inline int pop_circ_queue(struct ptr_ring * buffer, struct item * item_pop)
mutex_lock(&lock_pop);
struct item * item_temp;
/* extract one item struct containing two unsigned integers from the buffer */
item_temp = (struct item *)ptr_ring_consume_any(buffer);
if(item_temp) // (!= NULL)
item_pop->val1 = item_temp->val1;
item_pop->val2 = item_temp->val2;
// val1 will never be zero since the event number starts from 1 (so, val1 in push_circ_queue() will not be zero,
// same case after pop_circ_queue()), and 0 is only possible during initialization, not during pop_circ_queue()
//assert(item_pop->val1 != 0);
DEBUG_MSG(KERN_INFO "Before pop, head = %u , tail = %un", buffer->consumer_head, buffer->consumer_tail);
DEBUG_MSG(KERN_INFO "val1 = %u , val2 = %un", item_pop->val1, item_pop->val2);
DEBUG_MSG(KERN_INFO "After pop, head = %u , tail = %un", buffer->consumer_head, buffer->consumer_tail);
mutex_unlock(&lock_pop);
return 0;
else
//DEBUG_MSG(KERN_INFO "empty, nothing to pop from the ringn");
mutex_unlock(&lock_pop);
return 1;
void free_circ_queue(struct ptr_ring * q)
mutex_lock(&lock_cleanup);
ptr_ring_cleanup(q, NULL);
mutex_unlock(&lock_cleanup);
multithreading kernel buffer driver address-sanitizer
I am implementing single-producer,single-consumer ptr_ring buffers. Are there really data races within this linux driver code ?
I asked this because ThreadSanitizer gives me error and my system crashes after I started the ptr_ring code implementation.
I have added locks to push_circ_queue(), pop_circ_queue() and free_circ_queue(). Why does data race still occur ?
Edit:
I think I got why I still have data race
I have two different instances of ptr_ring, for sending (chnl_send) and receiving (chnl_recv) purposes respectively.
push_circ_queue() and pop_circ_queue() for the same ptr_ring should not be executed concurrently by interupt handler (push) and the corresponding thread (pop)
how would I code the mutex lock code in this case ?
a mutex that makes push_circ_queue(ptr_ring A) and pop_circ_queue(ptr_ring A) cannot be executed concurrently
same for push_circ_queue(ptr_ring B) and pop_circ_queue(ptr_ring B)
but the problem got worse when push_circ_queue() is inside a interrupt handler
Any help ?
/*
* Filename: circ_ring.c
* Version: 1.0
* Description: A circular buffer using API from
* https://github.com/torvalds/linux/blob/master/include/linux/ptr_ring.h
*/
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/ptr_ring.h>
#include "circ_ring.h"
//#include <assert.h>
#define DEBUG 1
#ifdef DEBUG
#define DEBUG_MSG(...) printk(__VA_ARGS__)
#else
#define DEBUG_MSG(...)
#endif
struct mutex lock_push;
struct mutex lock_pop;
struct mutex lock_cleanup;
struct ptr_ring * init_circ_queue(int len)
struct ptr_ring * q;
q = kzalloc(sizeof(struct ptr_ring), GFP_KERNEL);
if (q == NULL)
DEBUG_MSG(KERN_ERR "Not enough memory to allocate ptr_ring");
return NULL;
// creates an array of length 'len' where each array location can store a struct * item
if(ptr_ring_init(q, len, GFP_KERNEL) != 0)
DEBUG_MSG(KERN_ERR "Not enough memory to allocate ptr_ring array");
return NULL;
return q;
inline int push_circ_queue(struct ptr_ring * buffer, struct item * item_push)
mutex_lock(&lock_push);
/* insert one item into the buffer */
if(ptr_ring_produce_any(buffer, item_push) == 0) // operation is successful
DEBUG_MSG(KERN_INFO "Successfully pushed val1 = %u and val2 = %un", item_push->val1, item_push->val2);
mutex_unlock(&lock_push);
return 0;
else
DEBUG_MSG(KERN_INFO "full, not enough buffer spacen");
mutex_unlock(&lock_push);
return 1;
inline int pop_circ_queue(struct ptr_ring * buffer, struct item * item_pop)
mutex_lock(&lock_pop);
struct item * item_temp;
/* extract one item struct containing two unsigned integers from the buffer */
item_temp = (struct item *)ptr_ring_consume_any(buffer);
if(item_temp) // (!= NULL)
item_pop->val1 = item_temp->val1;
item_pop->val2 = item_temp->val2;
// val1 will never be zero since the event number starts from 1 (so, val1 in push_circ_queue() will not be zero,
// same case after pop_circ_queue()), and 0 is only possible during initialization, not during pop_circ_queue()
//assert(item_pop->val1 != 0);
DEBUG_MSG(KERN_INFO "Before pop, head = %u , tail = %un", buffer->consumer_head, buffer->consumer_tail);
DEBUG_MSG(KERN_INFO "val1 = %u , val2 = %un", item_pop->val1, item_pop->val2);
DEBUG_MSG(KERN_INFO "After pop, head = %u , tail = %un", buffer->consumer_head, buffer->consumer_tail);
mutex_unlock(&lock_pop);
return 0;
else
//DEBUG_MSG(KERN_INFO "empty, nothing to pop from the ringn");
mutex_unlock(&lock_pop);
return 1;
void free_circ_queue(struct ptr_ring * q)
mutex_lock(&lock_cleanup);
ptr_ring_cleanup(q, NULL);
mutex_unlock(&lock_cleanup);
multithreading kernel buffer driver address-sanitizer
multithreading kernel buffer driver address-sanitizer
edited 21 hours ago
kevin998x
407
407
asked Jan 8 at 4:22
kevinkevin
339
339
migrated from unix.stackexchange.com yesterday
This question came from our site for users of Linux, FreeBSD and other Un*x-like operating systems.
migrated from unix.stackexchange.com yesterday
This question came from our site for users of Linux, FreeBSD and other Un*x-like operating systems.
add a comment |
add a comment |
0
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54286731%2fdata-race-within-ptr-ring-code-implementation%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54286731%2fdata-race-within-ptr-ring-code-implementation%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown