فهرست منبع

msm: adsprpc: Usage of HLIST for async queue instead of LIST

To avoid queueing of a duplicate job that may belong to a freed ctx,
update async queue type from LIST to HLIST to avoid appending unhashed
nodes back to queue. Thread race can occur between thread undergoing
SSR routine and invoke response thread for FASTRPC_INVOKE2_ASYNC_RESPONSE
to queue job to the async queue.

Change-Id: Iebcd0e82f22ceb64d0f89e8458d6329c08c62bdc
Signed-off-by: Ansa Ahmed <[email protected]>
Ansa Ahmed 1 سال پیش
والد
کامیت
6087dc5827
2فایلهای تغییر یافته به همراه15 افزوده شده و 11 حذف شده
  1. 13 9
      dsp/adsprpc.c
  2. 2 2
      dsp/adsprpc_shared.h

+ 13 - 9
dsp/adsprpc.c

@@ -1876,8 +1876,9 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel,
 	}
 	}
 
 
 	INIT_HLIST_NODE(&ctx->hn);
 	INIT_HLIST_NODE(&ctx->hn);
-	INIT_LIST_HEAD(&ctx->asyncn);
+	INIT_HLIST_NODE(&ctx->asyncn);
 	hlist_add_fake(&ctx->hn);
 	hlist_add_fake(&ctx->hn);
+	hlist_add_fake(&ctx->asyncn);
 	ctx->fl = fl;
 	ctx->fl = fl;
 	ctx->maps = (struct fastrpc_mmap **)(&ctx[1]);
 	ctx->maps = (struct fastrpc_mmap **)(&ctx[1]);
 	ctx->lpra = (remote_arg_t *)(&ctx->maps[bufs]);
 	ctx->lpra = (remote_arg_t *)(&ctx->maps[bufs]);
@@ -2098,10 +2099,12 @@ static void fastrpc_queue_completed_async_job(struct smq_invoke_ctx *ctx)
 	spin_lock_irqsave(&fl->aqlock, flags);
 	spin_lock_irqsave(&fl->aqlock, flags);
 	if (ctx->is_early_wakeup)
 	if (ctx->is_early_wakeup)
 		goto bail;
 		goto bail;
-	list_add_tail(&ctx->asyncn, &fl->clst.async_queue);
-	atomic_add(1, &fl->async_queue_job_count);
-	ctx->is_early_wakeup = true;
-	wake_up_interruptible(&fl->async_wait_queue);
+	if (!hlist_unhashed(&ctx->asyncn)) {
+		hlist_add_head(&ctx->asyncn, &fl->clst.async_queue);
+		atomic_add(1, &fl->async_queue_job_count);
+		ctx->is_early_wakeup = true;
+		wake_up_interruptible(&fl->async_wait_queue);
+	}
 bail:
 bail:
 	spin_unlock_irqrestore(&fl->aqlock, flags);
 	spin_unlock_irqrestore(&fl->aqlock, flags);
 }
 }
@@ -2355,7 +2358,7 @@ static void context_list_ctor(struct fastrpc_ctx_lst *me)
 	INIT_HLIST_HEAD(&me->interrupted);
 	INIT_HLIST_HEAD(&me->interrupted);
 	INIT_HLIST_HEAD(&me->pending);
 	INIT_HLIST_HEAD(&me->pending);
 	me->num_active_ctxs = 0;
 	me->num_active_ctxs = 0;
-	INIT_LIST_HEAD(&me->async_queue);
+	INIT_HLIST_HEAD(&me->async_queue);
 	INIT_LIST_HEAD(&me->notif_queue);
 	INIT_LIST_HEAD(&me->notif_queue);
 }
 }
 
 
@@ -3502,10 +3505,11 @@ static int fastrpc_wait_on_async_queue(
 			struct fastrpc_file *fl)
 			struct fastrpc_file *fl)
 {
 {
 	int err = 0, ierr = 0, interrupted = 0, perfErr = 0;
 	int err = 0, ierr = 0, interrupted = 0, perfErr = 0;
-	struct smq_invoke_ctx *ctx = NULL, *ictx = NULL, *n = NULL;
+	struct smq_invoke_ctx *ctx = NULL, *ictx = NULL;
 	unsigned long flags;
 	unsigned long flags;
 	uint64_t *perf_counter = NULL;
 	uint64_t *perf_counter = NULL;
 	bool isworkdone = false;
 	bool isworkdone = false;
+	struct hlist_node *n;
 
 
 read_async_job:
 read_async_job:
 	interrupted = wait_event_interruptible(fl->async_wait_queue,
 	interrupted = wait_event_interruptible(fl->async_wait_queue,
@@ -3523,8 +3527,8 @@ read_async_job:
 		goto bail;
 		goto bail;
 
 
 	spin_lock_irqsave(&fl->aqlock, flags);
 	spin_lock_irqsave(&fl->aqlock, flags);
-	list_for_each_entry_safe(ictx, n, &fl->clst.async_queue, asyncn) {
-		list_del_init(&ictx->asyncn);
+	hlist_for_each_entry_safe(ictx, n, &fl->clst.async_queue, asyncn) {
+		hlist_del_init(&ictx->asyncn);
 		atomic_sub(1, &fl->async_queue_job_count);
 		atomic_sub(1, &fl->async_queue_job_count);
 		ctx = ictx;
 		ctx = ictx;
 		break;
 		break;

+ 2 - 2
dsp/adsprpc_shared.h

@@ -579,7 +579,7 @@ struct smq_notif_rsp {
 struct smq_invoke_ctx {
 struct smq_invoke_ctx {
 	struct hlist_node hn;
 	struct hlist_node hn;
 	/* Async node to add to async job ctx list */
 	/* Async node to add to async job ctx list */
-	struct list_head asyncn;
+	struct hlist_node asyncn;
 	struct completion work;
 	struct completion work;
 	int retval;
 	int retval;
 	int pid;
 	int pid;
@@ -631,7 +631,7 @@ struct fastrpc_ctx_lst {
 	/* Number of active contexts queued to DSP */
 	/* Number of active contexts queued to DSP */
 	uint32_t num_active_ctxs;
 	uint32_t num_active_ctxs;
 	/* Queue which holds all async job contexts of process */
 	/* Queue which holds all async job contexts of process */
-	struct list_head async_queue;
+	struct hlist_head async_queue;
 	/* Queue which holds all status notifications of process */
 	/* Queue which holds all status notifications of process */
 	struct list_head notif_queue;
 	struct list_head notif_queue;
 };
 };