I have a multithreaded linux app written in c running on a i.mx6 arm. I have a 25lc256 spi eeprom mapped to the file system. Writes are relatively slow at the driver level, not much can be done there. The problem is that file functions are blocking other threads for too long. usleep additions don’t seem to help, it appears I’ll have to do something different, but its not clear to me what to change.
The output on this calling this function from one thread is
EEprom write
EEprom saved in 522.000000 703.000000 705.000000 723.000000 662596.000000 1328858.000000
Capture -EPIPE snd_pcm_prepare
With Capture -EPIPE snd_pcm_prepare coming from the thread where the audio buffer underran because of the blocked thread, I suppose.
int SaveCurrentConfig(void) {//EEPROM int r = 1; struct timeval tvs, tv1, tv2, tv3, tv4, tv5, tv6; gettimeofday(&tvs, NULL); printf("EEprom writen"); pthread_mutex_lock(&eepromconfigmutex); { char * ConfigXml = BuildXmlConfig(); FILE * WriteConfig = fopen(ConfigPath, "w"); if (WriteConfig == NULL) { MyLog("Unable to open eeprom %sn", strerror(errno)); r = 0; goto badfinish; } gettimeofday(&tv1, NULL); size_t len = strlen(ConfigXml); unsigned short CRC = ComputeChecksum(ConfigXml, len); fwrite((char*) &len, 1, sizeof (size_t), WriteConfig); gettimeofday(&tv2, NULL); fwrite((char*) &CRC, 1, 2, WriteConfig); gettimeofday(&tv3, NULL); fwrite(ConfigXml, 1, strlen(ConfigXml), WriteConfig); gettimeofday(&tv4, NULL); fseek(WriteConfig, ConfigOffset2, SEEK_SET); fwrite((char*) &len, 1, sizeof (size_t), WriteConfig); fwrite((char*) &CRC, 1, 2, WriteConfig); fwrite(ConfigXml, 1, strlen(ConfigXml), WriteConfig); gettimeofday(&tv5, NULL); fclose(WriteConfig); badfinish: free(ConfigXml); } pthread_mutex_unlock(&eepromconfigmutex); gettimeofday(&tv6, NULL); double diff1 = time_diff(tvs, tv1); double diff2 = time_diff(tvs, tv2); double diff3 = time_diff(tvs, tv3); double diff4 = time_diff(tvs, tv4); double diff5 = time_diff(tvs, tv5); double diff6 = time_diff(tvs, tv6); printf("EEprom saved in %f %f %f %f %f %fn", diff1, diff2, diff3, diff4, diff5, diff6); return r; }
Advertisement
Answer
If that thread calling fclose()
is blocking other threads from running for long periods, then the problem is likely that it is spending a lot of time in kernel mode inside the eeprom driver code, flushing out the pending writes.
There’s a few things you could try:
- Ensure you’re running a kernel with the
PREEMPT
configuration option selected. This will allow the thread to be preempted while it’s running the eeprom driver code. - In conjunction with the first suggestion, set a higher scheduling priority for the sound thread (and/or a lower scheduling priority for the eeprom writing thread).
- Change your code to flush the writes out to the eeprom more frequently by calling
fflush()
after writing a smaller block of data (you may need to also callfsync()
on the underlying file descriptor).