misc: tegra-throughput: prevent race on init
Ilan Aelion [Sun, 5 Aug 2012 12:56:40 +0000 (06:56 -0600)]
prevent a race condition on initialization which could result in
multiple notifier registrations.

Bug 1027664

Change-Id: I2e7dcad159f631a7e244d43019169fdaf195bc34
(cherry picked from commit 06ad60cd85a221eec673654c73d55fba34455a3a)
Reviewed-on: http://git-master/r/121143
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Tested-by: Ilan Aelion <iaelion@nvidia.com>
Reviewed-by: Michael I Gold <gold@nvidia.com>

drivers/misc/tegra-throughput.c

index 2ab0e51..47dc682 100644 (file)
@@ -99,19 +99,24 @@ static int notifier_initialized;
 
 static int throughput_open(struct inode *inode, struct file *file)
 {
+       int need_init = 0;
+
+       spin_lock(&lock);
+
        if (!notifier_initialized) {
-               tegra_dc_register_flip_notifier(&throughput_flip_nb);
                notifier_initialized = 1;
+               need_init = 1;
        }
 
-       spin_lock(&lock);
-
        throughput_active_app_count++;
        if (throughput_active_app_count > 1)
                multiple_app_disable = 1;
 
        spin_unlock(&lock);
 
+       if (need_init)
+               tegra_dc_register_flip_notifier(&throughput_flip_nb);
+
        pr_debug("throughput_open node %p file %p\n", inode, file);
 
        return 0;
@@ -119,17 +124,22 @@ static int throughput_open(struct inode *inode, struct file *file)
 
 static int throughput_release(struct inode *inode, struct file *file)
 {
+       int need_deinit = 0;
+
        spin_lock(&lock);
-       throughput_active_app_count--;
-       spin_unlock(&lock);
 
+       throughput_active_app_count--;
        if (throughput_active_app_count == 0) {
                reset_target_frame_time();
                multiple_app_disable = 0;
-               tegra_dc_unregister_flip_notifier(&throughput_flip_nb);
                notifier_initialized = 0;
+               need_deinit = 1;
        }
 
+       spin_unlock(&lock);
+
+       if (need_deinit)
+               tegra_dc_unregister_flip_notifier(&throughput_flip_nb);
 
        pr_debug("throughput_release node %p file %p\n", inode, file);