*/
 static atomic_t tracers = ATOMIC_INIT(0);
 
-static inline void get_tracer(struct task_struct *task)
+static inline int get_tracer(struct task_struct *task)
 {
-       if (task)
+       int error;
+
+       spin_lock_irq(&ds_lock);
+
+       if (task) {
+               error = -EPERM;
+               if (atomic_read(&tracers) < 0)
+                       goto out;
                atomic_inc(&tracers);
-       else
+       } else {
+               error = -EPERM;
+               if (atomic_read(&tracers) > 0)
+                       goto out;
                atomic_dec(&tracers);
+       }
+
+       error = 0;
+out:
+       spin_unlock_irq(&ds_lock);
+       return error;
 }
 
 static inline void put_tracer(struct task_struct *task)
                atomic_inc(&tracers);
 }
 
-static inline int check_tracer(struct task_struct *task)
-{
-       return task ?
-               (atomic_read(&tracers) >= 0) :
-               (atomic_read(&tracers) <= 0);
-}
-
-
 /*
  * The DS context is either attached to a thread or to a cpu:
  * - in the former case, the thread_struct contains a pointer to the
        if (ovfl)
                goto out;
 
+       error = get_tracer(task);
+       if (error < 0)
+               goto out;
+
        /*
         * Per-cpu tracing is typically requested using smp_call_function().
         * We must not sleep.
        error = -ENOMEM;
        tracer = kzalloc(sizeof(*tracer), GFP_ATOMIC);
        if (!tracer)
-               goto out;
+               goto out_put_tracer;
        tracer->ovfl = ovfl;
 
        error = ds_request(&tracer->ds, &tracer->trace.ds,
 
        spin_lock_irqsave(&ds_lock, irq);
 
-       error = -EPERM;
-       if (!check_tracer(task))
-               goto out_unlock;
-       get_tracer(task);
-
        error = -EPERM;
        if (tracer->ds.context->bts_master)
-               goto out_put_tracer;
+               goto out_unlock;
        tracer->ds.context->bts_master = tracer;
 
        spin_unlock_irqrestore(&ds_lock, irq);
 
        return tracer;
 
- out_put_tracer:
-       put_tracer(task);
  out_unlock:
        spin_unlock_irqrestore(&ds_lock, irq);
        ds_put_context(tracer->ds.context);
  out_tracer:
        kfree(tracer);
+ out_put_tracer:
+       put_tracer(task);
  out:
        return ERR_PTR(error);
 }
        if (ovfl)
                goto out;
 
+       error = get_tracer(task);
+       if (error < 0)
+               goto out;
+
        /*
         * Per-cpu tracing is typically requested using smp_call_function().
         * We must not sleep.
        error = -ENOMEM;
        tracer = kzalloc(sizeof(*tracer), GFP_ATOMIC);
        if (!tracer)
-               goto out;
+               goto out_put_tracer;
        tracer->ovfl = ovfl;
 
        error = ds_request(&tracer->ds, &tracer->trace.ds,
 
        spin_lock_irqsave(&ds_lock, irq);
 
-       error = -EPERM;
-       if (!check_tracer(task))
-               goto out_unlock;
-       get_tracer(task);
-
        error = -EPERM;
        if (tracer->ds.context->pebs_master)
-               goto out_put_tracer;
+               goto out_unlock;
        tracer->ds.context->pebs_master = tracer;
 
        spin_unlock_irqrestore(&ds_lock, irq);
 
        return tracer;
 
- out_put_tracer:
-       put_tracer(task);
  out_unlock:
        spin_unlock_irqrestore(&ds_lock, irq);
        ds_put_context(tracer->ds.context);
  out_tracer:
        kfree(tracer);
+ out_put_tracer:
+       put_tracer(task);
  out:
        return ERR_PTR(error);
 }
        if (task && (task != current))
                wait_task_context_switch(task);
 
-       put_tracer(task);
        ds_put_context(tracer->ds.context);
+       put_tracer(task);
 
        kfree(tracer);
 }
 
 void ds_release_pebs(struct pebs_tracer *tracer)
 {
+       struct task_struct *task;
+
        if (!tracer)
                return;
 
+       task = tracer->ds.context->task;
+
        ds_suspend_pebs(tracer);
 
        WARN_ON_ONCE(tracer->ds.context->pebs_master != tracer);
        tracer->ds.context->pebs_master = NULL;
 
-       put_tracer(tracer->ds.context->task);
        ds_put_context(tracer->ds.context);
+       put_tracer(task);
 
        kfree(tracer);
 }