Changeset 1626
- Timestamp:
- 08/21/09 21:32:03 (14 years ago)
- Files:
-
- trunk/libffado/src/rme/rme_shm.cpp (modified) (7 diffs)
- trunk/libffado/src/SConscript (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/libffado/src/rme/rme_shm.cpp
r1624 r1626 44 44 #define RME_SHM_SIZE sizeof(rme_shm_t) 45 45 46 #define RME_SHM_LOCKNAME "/ffado:rme_shm_lock" 47 46 48 #include <unistd.h> 47 49 #include <errno.h> … … 52 54 #include "rme_shm.h" 53 55 56 static signed int rme_shm_lock(void) { 57 signed lockfd; 58 59 do { 60 // The check for existance and shm creation are atomic so it's save 61 // to use this as the basis for a global lock. 62 lockfd = shm_open(RME_SHM_LOCKNAME, O_RDWR | O_CREAT | O_EXCL, 0644); 63 if (lockfd < 0) 64 usleep(10000); 65 } while (lockfd < 0); 66 67 return lockfd; 68 } 69 70 static void rme_shm_unlock(signed int lockfd) { 71 close(lockfd); 72 shm_unlink(RME_SHM_LOCKNAME); 73 } 74 54 75 rme_shm_t *rme_shm_open(void) { 55 76 56 signed int shmfd ;77 signed int shmfd, lockfd; 57 78 rme_shm_t *data; 58 79 signed int created = 0; 59 80 60 // There is a small race condition here - if another RME FFADO process 61 // closes between the first and second shm_open() calls and in doing so 62 // removes the shm object, the current process will end up without a shm 63 // object since the second shm_open() call will fail. At this point the 64 // practical likelihood of this is low, so we'll live with it. 65 shmfd = shm_open(RME_SHM_NAME, O_RDWR | O_CREAT | O_EXCL, 0644); 81 lockfd = rme_shm_lock(); 82 83 shmfd = shm_open(RME_SHM_NAME, O_RDWR, 0644); 66 84 if (shmfd < 0) { 67 if (errno ==EEXIST) {68 shmfd = shm_open(RME_SHM_NAME, O_RDWR , 0644);69 if (shmfd < 0) 85 if (errno == ENOENT) { 86 shmfd = shm_open(RME_SHM_NAME, O_RDWR | O_CREAT | O_EXCL, 0644); 87 if (shmfd < 0) 70 88 return NULL; 71 } else { 89 else { 90 ftruncate(shmfd, RME_SHM_SIZE); 91 created = 1; 92 } 93 } else 72 94 return NULL; 73 }74 } else {75 ftruncate(shmfd, RME_SHM_SIZE);76 created = 1;77 95 } 78 96 … … 87 105 } 88 106 89 // There's another unlikely race condition here. If another process has90 // done rme_shm_close() which results in a zero reference count between91 // our second shm_open() call and here, we will be mapped to a shared92 // object which is inaccessible to any subsequent processes due to the93 // shm_unlink() call in rme_shm_close(). Again though, the practical94 // changes of this occurring are low.95 107 pthread_mutex_lock(&data->lock); 96 108 data->ref_count++; … … 98 110 data->valid++; 99 111 pthread_mutex_unlock(&data->lock); 112 113 rme_shm_unlock(lockfd); 100 114 101 115 return data; … … 105 119 106 120 signed int unlink = 0; 121 signed int lockfd; 122 123 lockfd = rme_shm_lock(); 107 124 108 125 pthread_mutex_lock(&shm_data->lock); … … 112 129 pthread_mutex_unlock(&shm_data->lock); 113 130 114 // There's nothing to gain by explicitly calling pthread_mutex_destroy() 115 // on shm_data->lock, and doing so could cause issues for other processes 116 // which were waiting on the lock during the previous code block. 131 if (unlink) { 132 // This is safe: if the reference count is zero there can't be any 133 // other process using the lock at this point. 134 pthread_mutex_destroy(&shm_data->lock); 135 } 117 136 118 137 munmap(shm_data, RME_SHM_SIZE); … … 120 139 if (unlink) 121 140 shm_unlink(RME_SHM_NAME); 141 142 rme_shm_unlock(lockfd); 122 143 } trunk/libffado/src/SConscript
r1599 r1626 170 170 171 171 rme_source = env.Split( '\ 172 rme/rme_shm.cpp \ 172 173 rme/rme_avdevice.cpp \ 173 174 rme/rme_avdevice_settings.cpp \