0

I have a single board computer with a I2C GPIO expander device, listed as /dev/i2c-0. In my multithreaded program I open() this character device and read/write to it on separate threads using i2c_smbus_write_byte_data and friends from the libi2c library, but I am not sure if that is thread-safe.

I have seen kernel space GPIO driver implementations that bind over the I2C character device and allow to interface with the device as if it was a GPIO device (pca953x driver) and they have internal mutexes within every gpio_set/get function. In another question people say i2c_smbus_* functions have internal mutexes so I cannot be sure.

Is this kind of concurrent access thread-safe?

void *thread_fn(void *arg){
 int fd = *(int*)arg;
 uint16_t d;
 for(uint16_t i=0;i<1000;i++) {
 if (i%2==0){
 d = i2c_smbus_read_word_data(fd, REG);
 } else {
 d |= 1 << (i%16);
 i2c_smbus_write_word_data(fd, REG, d);
 }
 }
 return NULL;
}
int main(void){
 int fd = open("/dev/i2c-0");
 pthread_t t;
 pthread_create(&t, NULL, thread_fn, &fd);
 for(uint16_t i=0;i<1000;i++)
 i2c_smbus_write_word_data(fd, REG, i);
 pthread_join(t, NULL);
 return 0;
}
Clifford
94.3k14 gold badges93 silver badges176 bronze badges
asked Oct 17 at 14:38
3
  • 1
    Why don’t you use the kernel driver for that expander which is definitely thread-safe? Commented Oct 20 at 10:33
  • @0andriy On the IO, I need a precise square wave output at high frequencies up to 8kHz. That is not feasible with the gpio driver (I measured with an oscilloscope) and I assume the reason is the constant locking/unlocking. On the contrary, when I interface with it as a I2C device, I can go up to high frequencies even with a userspace mutex and careful scheduling of the IO access. That's what made me think that maybe the mutex in the driver is redundant. Commented Oct 20 at 11:36
  • 1
    No, the problem is the choosen (SW) tool. Linux kernel is General Purpose multi-tasking OS, doing what you want requires quite a high priority task to guarantee the desired latency. You may consider PREEMPT_RT kernel, but still the application needs to be properly written for that. What you have working is just by luck (mostly idling system, with likely a single user which also does nothing). That said, using in-kernel driver is a good start (and user space driver for I²C component like that in GP OS is quite controversial move). Commented Oct 20 at 18:09

0

Know someone who can answer? Share a link to this question via email, Twitter, or Facebook.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.