msm: camera: sync: protect sync obj creation from race condition
Multiple thread can find the same sync obj and waiting for lock.
If the spinlock releases after another thread finds a sync obj,
there is possibility that they will get the same id. Use atomic
operation to ensure obj is free.
Change-Id: I1d3c40f2c0315d27ecf11b953a3c9bdb89d41ef8
Signed-off-by: Junzhe Zou <jnzhezou@codeaurora.org>
diff --git a/drivers/media/platform/msm/camera/cam_sync/cam_sync.c b/drivers/media/platform/msm/camera/cam_sync/cam_sync.c
index 37d612b..2422016 100644
--- a/drivers/media/platform/msm/camera/cam_sync/cam_sync.c
+++ b/drivers/media/platform/msm/camera/cam_sync/cam_sync.c
@@ -25,22 +25,25 @@
{
int rc;
long idx;
+ bool bit;
do {
idx = find_first_zero_bit(sync_dev->bitmap, CAM_SYNC_MAX_OBJS);
if (idx >= CAM_SYNC_MAX_OBJS)
return -ENOMEM;
- } while (!spin_trylock_bh(&sync_dev->row_spinlocks[idx]));
+ bit = test_and_set_bit(idx, sync_dev->bitmap);
+ } while (bit);
+ spin_lock_bh(&sync_dev->row_spinlocks[idx]);
rc = cam_sync_init_object(sync_dev->sync_table, idx, name);
if (rc) {
CAM_ERR(CAM_SYNC, "Error: Unable to init row at idx = %ld",
idx);
+ clear_bit(idx, sync_dev->bitmap);
spin_unlock_bh(&sync_dev->row_spinlocks[idx]);
return -EINVAL;
}
- set_bit(idx, sync_dev->bitmap);
*sync_obj = idx;
spin_unlock_bh(&sync_dev->row_spinlocks[idx]);
@@ -299,6 +302,7 @@
{
int rc;
long idx = 0;
+ bool bit;
if (!sync_obj || !merged_obj) {
CAM_ERR(CAM_SYNC, "Invalid pointer(s)");
@@ -316,9 +320,10 @@
idx = find_first_zero_bit(sync_dev->bitmap, CAM_SYNC_MAX_OBJS);
if (idx >= CAM_SYNC_MAX_OBJS)
return -ENOMEM;
- } while (!spin_trylock_bh(&sync_dev->row_spinlocks[idx]));
+ bit = test_and_set_bit(idx, sync_dev->bitmap);
+ } while (bit);
- set_bit(idx, sync_dev->bitmap);
+ spin_lock_bh(&sync_dev->row_spinlocks[idx]);
rc = cam_sync_init_group_object(sync_dev->sync_table,
idx, sync_obj,
@@ -326,6 +331,7 @@
if (rc < 0) {
CAM_ERR(CAM_SYNC, "Error: Unable to init row at idx = %ld",
idx);
+ clear_bit(idx, sync_dev->bitmap);
spin_unlock_bh(&sync_dev->row_spinlocks[idx]);
return -EINVAL;
}