void cpupri_set(struct cpupri *cp, int cpu, int newpri) { int *currpri = &cp->cpu_to_pri[cpu]; int oldpri = *currpri; int do_mb = 0; newpri = convert_prio(newpri); BUG_ON(newpri >= CPUPRI_NR_PRIORITIES); if (newpri == oldpri) return; if (likely(newpri != CPUPRI_INVALID)) { struct cpupri_vec *vec = &cp->pri_to_cpu[newpri]; cpumask_set_cpu(cpu, vec->mask); smp_mb__before_atomic_inc(); atomic_inc(&(vec)->count); do_mb = 1; } if (likely(oldpri != CPUPRI_INVALID)) { struct cpupri_vec *vec = &cp->pri_to_cpu[oldpri]; if (do_mb) smp_mb__after_atomic_inc(); atomic_dec(&(vec)->count); smp_mb__after_atomic_inc(); cpumask_clear_cpu(cpu, vec->mask); } *currpri = newpri; }
static void rcu_idle_enter_common(struct rcu_dynticks *rdtp, long long oldval) { trace_rcu_dyntick("Start", oldval, 0); if (!is_idle_task(current)) { struct task_struct *idle = idle_task(smp_processor_id()); trace_rcu_dyntick("Error on entry: not idle task", oldval, 0); ftrace_dump(DUMP_ALL); WARN_ONCE(1, "Current pid: %d comm: %s / Idle pid: %d comm: %s", current->pid, current->comm, idle->pid, idle->comm); } rcu_prepare_for_idle(smp_processor_id()); smp_mb__before_atomic_inc(); atomic_inc(&rdtp->dynticks); smp_mb__after_atomic_inc(); WARN_ON_ONCE(atomic_read(&rdtp->dynticks) & 0x1); rcu_lockdep_assert(!lock_is_held(&rcu_lock_map), "Illegal idle entry in RCU read-side critical section."); rcu_lockdep_assert(!lock_is_held(&rcu_bh_lock_map), "Illegal idle entry in RCU-bh read-side critical section."); rcu_lockdep_assert(!lock_is_held(&rcu_sched_lock_map), "Illegal idle entry in RCU-sched read-side critical section."); }
static void iblock_bio_done(struct bio *bio, int err) { struct se_cmd *cmd = bio->bi_private; struct iblock_req *ibr = cmd->priv; /* * Set -EIO if !BIO_UPTODATE and the passed is still err=0 */ if (!test_bit(BIO_UPTODATE, &bio->bi_flags) && !err) err = -EIO; if (err != 0) { pr_err("test_bit(BIO_UPTODATE) failed for bio: %p," " err: %d\n", bio, err); /* * Bump the ib_bio_err_cnt and release bio. */ atomic_inc(&ibr->ib_bio_err_cnt); smp_mb__after_atomic_inc(); } bio_put(bio); iblock_complete_cmd(cmd); }
/** * kref_get - increment refcount for object. * @kref: object. */ void kref_get(struct kref *kref) { if(!atomic_read(&kref->refcount)) printk(KERN_WARNING "%s failed for atomic_read\n", __func__); /* TD 80761 WARN_ON(!atomic_read(&kref->refcount)); */ atomic_inc(&kref->refcount); smp_mb__after_atomic_inc(); }
void rcu_nmi_exit(void) { struct rcu_dynticks *rdtp = &__get_cpu_var(rcu_dynticks); if (rdtp->dynticks_nmi_nesting == 0 || --rdtp->dynticks_nmi_nesting != 0) return; smp_mb__before_atomic_inc(); atomic_inc(&rdtp->dynticks); smp_mb__after_atomic_inc(); WARN_ON_ONCE(atomic_read(&rdtp->dynticks) & 0x1); }
void rcu_nmi_enter(void) { struct rcu_dynticks *rdtp = &__get_cpu_var(rcu_dynticks); if (rdtp->dynticks_nmi_nesting == 0 && (atomic_read(&rdtp->dynticks) & 0x1)) return; rdtp->dynticks_nmi_nesting++; smp_mb__before_atomic_inc(); atomic_inc(&rdtp->dynticks); smp_mb__after_atomic_inc(); WARN_ON_ONCE(!(atomic_read(&rdtp->dynticks) & 0x1)); }
/** * drm_update_vblank_count - update the master vblank counter * @dev: DRM device * @crtc: counter to update * * Call back into the driver to update the appropriate vblank counter * (specified by @crtc). Deal with wraparound, if it occurred, and * update the last read value so we can deal with wraparound on the next * call if necessary. * * Only necessary when going from off->on, to account for frames we * didn't get an interrupt for. * * Note: caller must hold dev->vbl_lock since this reads & writes * device vblank fields. */ static void drm_update_vblank_count(struct drm_device *dev, int crtc) { u32 cur_vblank, diff, tslot, rc; struct timeval t_vblank; /* * Interrupts were disabled prior to this call, so deal with counter * wrap if needed. * NOTE! It's possible we lost a full dev->max_vblank_count events * here if the register is small or we had vblank interrupts off for * a long time. * * We repeat the hardware vblank counter & timestamp query until * we get consistent results. This to prevent races between gpu * updating its hardware counter while we are retrieving the * corresponding vblank timestamp. */ do { cur_vblank = dev->driver->get_vblank_counter(dev, crtc); rc = drm_get_last_vbltimestamp(dev, crtc, &t_vblank, 0); } while (cur_vblank != dev->driver->get_vblank_counter(dev, crtc)); /* Deal with counter wrap */ diff = cur_vblank - dev->last_vblank[crtc]; if (cur_vblank < dev->last_vblank[crtc]) { diff += dev->max_vblank_count; DRM_DEBUG("last_vblank[%d]=0x%x, cur_vblank=0x%x => diff=0x%x\n", crtc, dev->last_vblank[crtc], cur_vblank, diff); } DPRINTF("enabling vblank interrupts on crtc %d, missed %d\n", crtc, diff); /* Reinitialize corresponding vblank timestamp if high-precision query * available. Skip this step if query unsupported or failed. Will * reinitialize delayed at next vblank interrupt in that case. */ if (rc) { tslot = atomic_read(&dev->_vblank_count[crtc]) + diff; vblanktimestamp(dev, crtc, tslot) = t_vblank; } smp_mb__before_atomic_inc(); atomic_add(diff, &dev->_vblank_count[crtc]); smp_mb__after_atomic_inc(); }
static int tcm_loop_port_link( struct se_portal_group *se_tpg, struct se_lun *lun) { struct tcm_loop_tpg *tl_tpg = container_of(se_tpg, struct tcm_loop_tpg, tl_se_tpg); struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba; atomic_inc(&tl_tpg->tl_tpg_port_count); smp_mb__after_atomic_inc(); /* * Add Linux/SCSI struct scsi_device by HCTL */ scsi_add_device(tl_hba->sh, 0, tl_tpg->tl_tpgt, lun->unpacked_lun); pr_debug("TCM_Loop_ConfigFS: Port Link Successful\n"); return 0; }
static void rcu_idle_exit_common(struct rcu_dynticks *rdtp, long long oldval) { smp_mb__before_atomic_inc(); atomic_inc(&rdtp->dynticks); smp_mb__after_atomic_inc(); WARN_ON_ONCE(!(atomic_read(&rdtp->dynticks) & 0x1)); rcu_cleanup_after_idle(smp_processor_id()); trace_rcu_dyntick("End", oldval, rdtp->dynticks_nesting); if (!is_idle_task(current)) { struct task_struct *idle = idle_task(smp_processor_id()); trace_rcu_dyntick("Error on exit: not idle task", oldval, rdtp->dynticks_nesting); ftrace_dump(DUMP_ALL); WARN_ONCE(1, "Current pid: %d comm: %s / Idle pid: %d comm: %s", current->pid, current->comm, idle->pid, idle->comm); } }
void crash_ipi_callback(struct pt_regs *regs) { static cpumask_t cpus_state_saved = CPU_MASK_NONE; int cpu = smp_processor_id(); if (!cpu_online(cpu)) return; hard_irq_disable(); if (!cpumask_test_cpu(cpu, &cpus_state_saved)) { crash_save_cpu(regs, cpu); cpumask_set_cpu(cpu, &cpus_state_saved); } atomic_inc(&cpus_in_crash); smp_mb__after_atomic_inc(); /* * Starting the kdump boot. * This barrier is needed to make sure that all CPUs are stopped. */ while (!time_to_dump) cpu_relax(); if (ppc_md.kexec_cpu_down) ppc_md.kexec_cpu_down(1, 1); #ifdef CONFIG_PPC64 kexec_smp_wait(); #else for (;;); /* FIXME */ #endif /* NOTREACHED */ }
/** * cpupri_set - update the cpu priority setting * @cp: The cpupri context * @cpu: The target cpu * @newpri: The priority (INVALID-RT99) to assign to this CPU * * Note: Assumes cpu_rq(cpu)->lock is locked * * Returns: (void) */ void cpupri_set(struct cpupri *cp, int cpu, int newpri) { int *currpri = &cp->cpu_to_pri[cpu]; int oldpri = *currpri; int do_mb = 0; newpri = convert_prio(newpri); BUG_ON(newpri >= CPUPRI_NR_PRIORITIES); if (newpri == oldpri) return; /* * If the cpu was currently mapped to a different value, we * need to map it to the new value then remove the old value. * Note, we must add the new value first, otherwise we risk the * cpu being missed by the priority loop in cpupri_find. */ if (likely(newpri != CPUPRI_INVALID)) { struct cpupri_vec *vec = &cp->pri_to_cpu[newpri]; cpumask_set_cpu(cpu, vec->mask); /* * When adding a new vector, we update the mask first, * do a write memory barrier, and then update the count, to * make sure the vector is visible when count is set. */ smp_mb__before_atomic_inc(); atomic_inc(&(vec)->count); do_mb = 1; } if (likely(oldpri != CPUPRI_INVALID)) { struct cpupri_vec *vec = &cp->pri_to_cpu[oldpri]; /* * Because the order of modification of the vec->count * is important, we must make sure that the update * of the new prio is seen before we decrement the * old prio. This makes sure that the loop sees * one or the other when we raise the priority of * the run queue. We don't care about when we lower the * priority, as that will trigger an rt pull anyway. * * We only need to do a memory barrier if we updated * the new priority vec. */ if (do_mb) smp_mb__after_atomic_inc(); /* * When removing from the vector, we decrement the counter first * do a memory barrier and then clear the mask. */ atomic_dec(&(vec)->count); smp_mb__after_atomic_inc(); cpumask_clear_cpu(cpu, vec->mask); } *currpri = newpri; }
static void genpd_sd_counter_inc(struct generic_pm_domain *genpd) { atomic_inc(&genpd->sd_count); smp_mb__after_atomic_inc(); }
/** * kref_get - increment refcount for object. * @kref: object. */ void kref_get(struct kref *kref) { WARN_ON(!atomic_read(&kref->refcount)); atomic_inc(&kref->refcount); smp_mb__after_atomic_inc(); }
static inline void ccids_read_lock(void) { atomic_inc(&ccids_lockct); smp_mb__after_atomic_inc(); spin_unlock_wait(&ccids_lock); }
static void helper_lock(void) { atomic_inc(&running_helpers); smp_mb__after_atomic_inc(); }
/* * Disable vblank irq's on crtc, make sure that last vblank count * of hardware and corresponding consistent software vblank counter * are preserved, even if there are any spurious vblank irq's after * disable. */ static void vblank_disable_and_save(struct drm_device *dev, int crtc) { u32 vblcount; s64 diff_ns; int vblrc; struct timeval tvblank; int count = DRM_TIMESTAMP_MAXRETRIES; /* Prevent vblank irq processing while disabling vblank irqs, * so no updates of timestamps or count can happen after we've * disabled. Needed to prevent races in case of delayed irq's. */ mtx_enter(&dev->vblank_time_lock); dev->driver->disable_vblank(dev, crtc); dev->vblank_enabled[crtc] = 0; /* No further vblank irq's will be processed after * this point. Get current hardware vblank count and * vblank timestamp, repeat until they are consistent. * * FIXME: There is still a race condition here and in * drm_update_vblank_count() which can cause off-by-one * reinitialization of software vblank counter. If gpu * vblank counter doesn't increment exactly at the leading * edge of a vblank interval, then we can lose 1 count if * we happen to execute between start of vblank and the * delayed gpu counter increment. */ do { dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc); vblrc = drm_get_last_vbltimestamp(dev, crtc, &tvblank, 0); } while (dev->last_vblank[crtc] != dev->driver->get_vblank_counter(dev, crtc) && (--count) && vblrc); if (!count) vblrc = 0; /* Compute time difference to stored timestamp of last vblank * as updated by last invocation of drm_handle_vblank() in vblank irq. */ vblcount = atomic_read(&dev->_vblank_count[crtc]); diff_ns = timeval_to_ns(&tvblank) - timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount)); /* If there is at least 1 msec difference between the last stored * timestamp and tvblank, then we are currently executing our * disable inside a new vblank interval, the tvblank timestamp * corresponds to this new vblank interval and the irq handler * for this vblank didn't run yet and won't run due to our disable. * Therefore we need to do the job of drm_handle_vblank() and * increment the vblank counter by one to account for this vblank. * * Skip this step if there isn't any high precision timestamp * available. In that case we can't account for this and just * hope for the best. */ if ((vblrc > 0) && (abs64(diff_ns) > 1000000)) { atomic_inc(&dev->_vblank_count[crtc]); smp_mb__after_atomic_inc(); } /* Invalidate all timestamps while vblank irq's are off. */ clear_vblank_timestamps(dev, crtc); mtx_leave(&dev->vblank_time_lock); }