Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 688c22c7 authored by Junzhe Zou's avatar Junzhe Zou
Browse files

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: default avatarJunzhe Zou <jnzhezou@codeaurora.org>
parent 2152c7bc
Loading
Loading
Loading
Loading
+10 −4
Original line number Diff line number Diff line
@@ -25,22 +25,25 @@ int cam_sync_create(int32_t *sync_obj, const char *name)
{
	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 cam_sync_merge(int32_t *sync_obj, uint32_t num_objs, int32_t *merged_obj)
{
	int rc;
	long idx = 0;
	bool bit;

	if (!sync_obj || !merged_obj) {
		CAM_ERR(CAM_SYNC, "Invalid pointer(s)");
@@ -316,9 +320,10 @@ int cam_sync_merge(int32_t *sync_obj, uint32_t num_objs, int32_t *merged_obj)
		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 @@ int cam_sync_merge(int32_t *sync_obj, uint32_t num_objs, int32_t *merged_obj)
	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;
	}