void debug_rt_mutex_init_waiter(struct rt_mutex_waiter *waiter) { memset(waiter, 0x11, sizeof(*waiter)); plist_node_init(&waiter->list_entry, MAX_PRIO); plist_node_init(&waiter->pi_list_entry, MAX_PRIO); waiter->deadlock_task_pid = NULL; }
static int memc_min_pwr_update(struct kona_memc *kmemc, struct kona_memc_node *memc_node, int action) { u32 new_val; int ret = 0; spin_lock(&kmemc->memc_lock); switch (action) { case MEMC_NODE_ADD: plist_node_init(&memc_node->node, memc_node->min_pwr); plist_add(&memc_node->node, &kmemc->min_pwr_list); break; case MEMC_NODE_DEL: plist_del(&memc_node->node, &kmemc->min_pwr_list); break; case MEMC_NODE_UPDATE: plist_del(&memc_node->node, &kmemc->min_pwr_list); plist_node_init(&memc_node->node, memc_node->min_pwr); plist_add(&memc_node->node, &kmemc->min_pwr_list); break; default: BUG(); return -EINVAL; } new_val = plist_last(&kmemc->min_pwr_list)->prio; if (new_val != kmemc->active_min_pwr) { ret = memc_set_min_pwr(kmemc, new_val, MEMC_AP_MIN_PWR); if (!ret) kmemc->active_min_pwr = new_val; } spin_unlock(&kmemc->memc_lock); return ret; }
/* * Task blocks on lock. * * Prepare waiter and propagate pi chain * * This must be called with lock->wait_lock held. */ static int task_blocks_on_rt_mutex(struct rt_mutex *lock, struct rt_mutex_waiter *waiter, int detect_deadlock) { struct task_struct *owner = rt_mutex_owner(lock); struct rt_mutex_waiter *top_waiter = waiter; unsigned long flags; int boost = 0, res; spin_lock_irqsave(¤t->pi_lock, flags); __rt_mutex_adjust_prio(current); waiter->task = current; waiter->lock = lock; plist_node_init(&waiter->list_entry, current->prio); plist_node_init(&waiter->pi_list_entry, current->prio); /* Get the top priority waiter on the lock */ if (rt_mutex_has_waiters(lock)) top_waiter = rt_mutex_top_waiter(lock); plist_add(&waiter->list_entry, &lock->wait_list); current->pi_blocked_on = waiter; spin_unlock_irqrestore(¤t->pi_lock, flags); if (waiter == rt_mutex_top_waiter(lock)) { spin_lock_irqsave(&owner->pi_lock, flags); plist_del(&top_waiter->pi_list_entry, &owner->pi_waiters); plist_add(&waiter->pi_list_entry, &owner->pi_waiters); __rt_mutex_adjust_prio(owner); if (owner->pi_blocked_on) { boost = 1; /* gets dropped in rt_mutex_adjust_prio_chain()! */ get_task_struct(owner); } spin_unlock_irqrestore(&owner->pi_lock, flags); } else if (debug_rt_mutex_detect_deadlock(waiter, detect_deadlock)) { spin_lock_irqsave(&owner->pi_lock, flags); if (owner->pi_blocked_on) { boost = 1; /* gets dropped in rt_mutex_adjust_prio_chain()! */ get_task_struct(owner); } spin_unlock_irqrestore(&owner->pi_lock, flags); } if (!boost) return 0; spin_unlock(&lock->wait_lock); res = rt_mutex_adjust_prio_chain(owner, detect_deadlock, lock, waiter, current); spin_lock(&lock->wait_lock); return res; }
/* * Task blocks on lock. * * Prepare waiter and propagate pi chain * * This must be called with lock->wait_lock held. */ static int task_blocks_on_rt_mutex(struct rt_mutex *lock, struct rt_mutex_waiter *waiter, struct task_struct *task, int detect_deadlock) { struct task_struct *owner = rt_mutex_owner(lock); struct rt_mutex_waiter *top_waiter = waiter; unsigned long flags; int chain_walk = 0, res; raw_spin_lock_irqsave(&task->pi_lock, flags); __rt_mutex_adjust_prio(task); waiter->task = task; waiter->lock = lock; plist_node_init(&waiter->list_entry, task->prio); plist_node_init(&waiter->pi_list_entry, task->prio); /* Get the top priority waiter on the lock */ if (rt_mutex_has_waiters(lock)) top_waiter = rt_mutex_top_waiter(lock); plist_add(&waiter->list_entry, &lock->wait_list); task->pi_blocked_on = waiter; raw_spin_unlock_irqrestore(&task->pi_lock, flags); if (waiter == rt_mutex_top_waiter(lock)) { raw_spin_lock_irqsave(&owner->pi_lock, flags); plist_del(&top_waiter->pi_list_entry, &owner->pi_waiters); plist_add(&waiter->pi_list_entry, &owner->pi_waiters); __rt_mutex_adjust_prio(owner); if (owner->pi_blocked_on) chain_walk = 1; raw_spin_unlock_irqrestore(&owner->pi_lock, flags); } else if (debug_rt_mutex_detect_deadlock(waiter, detect_deadlock)) chain_walk = 1; if (!chain_walk) return 0; /* * The owner can't disappear while holding a lock, * so the owner struct is protected by wait_lock. * Gets dropped in rt_mutex_adjust_prio_chain()! */ get_task_struct(owner); raw_spin_unlock(&lock->wait_lock); res = rt_mutex_adjust_prio_chain(owner, detect_deadlock, lock, waiter, task); raw_spin_lock(&lock->wait_lock); return res; }
static struct kgsl_page_pool *kgsl_page_pool_create(gfp_t gfp_mask, unsigned int order, unsigned int reserve, bool reserve_only) { struct kgsl_page_pool *pool = kmalloc(sizeof(struct kgsl_page_pool), GFP_KERNEL); if (!pool) return NULL; pool->reserve_only = reserve_only; pool->count = 0; pool->reserve_count = 0; INIT_LIST_HEAD(&pool->items); pool->gfp_mask = gfp_mask | __GFP_COMP; pool->order = order; mutex_init(&pool->mutex); plist_node_init(&pool->list, order); if (reserve) { unsigned int i; for (i = 0; i < reserve; i++) { struct page *page = kgsl_page_pool_alloc_pages(pool); if (page == NULL) { // TODO: fix possible pool leak here // then again, this should never happen and will be a critical error kgsl_page_pool_destroy(pool); return NULL; } kgsl_page_pool_add(pool, page); } pool->reserve_count = reserve; } return pool; }
static void enqueue_pushable_task(struct rq *rq, struct task_struct *p) { plist_del(&p->pushable_tasks, &rq->rt.pushable_tasks); plist_node_init(&p->pushable_tasks, p->prio); plist_add(&p->pushable_tasks, &rq->rt.pushable_tasks); /* Update the highest prio pushable task */ if (p->prio < rq->rt.highest_prio.next) rq->rt.highest_prio.next = p->prio; }
/** * pm_qos_update_target - manages the constraints list and calls the notifiers * if needed * @c: constraints data struct * @node: request to add to the list, to update or to remove * @action: action to take on the constraints list * @value: value of the request to add or update * * This function returns 1 if the aggregated constraint value has changed, 0 * otherwise. */ int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node *node, enum pm_qos_req_action action, int value) { unsigned long flags; int prev_value, curr_value, new_value; spin_lock_irqsave(&pm_qos_lock, flags); prev_value = pm_qos_get_value(c); if (value == PM_QOS_DEFAULT_VALUE) new_value = c->default_value; else new_value = value; switch (action) { case PM_QOS_REMOVE_REQ: plist_del(node, &c->list); break; case PM_QOS_UPDATE_REQ: /* * to change the list, we atomically remove, reinit * with new value and add, then see if the extremal * changed */ plist_del(node, &c->list); case PM_QOS_ADD_REQ: plist_node_init(node, new_value); plist_add(node, &c->list); break; default: /* no action */ ; } curr_value = pm_qos_get_value(c); pm_qos_set_value(c, curr_value); spin_unlock_irqrestore(&pm_qos_lock, flags); if (prev_value != curr_value) { blocking_notifier_call_chain(c->notifiers, (unsigned long)curr_value, NULL); return 1; } else { return 0; } }
/** * adreno_drawctxt_create - create a new adreno draw context * @dev_priv: the owner of the context * @flags: flags for the context (passed from user space) * * Create and return a new draw context for the 3D core. */ struct kgsl_context * adreno_drawctxt_create(struct kgsl_device_private *dev_priv, uint32_t *flags) { struct adreno_context *drawctxt; struct kgsl_device *device = dev_priv->device; int ret; drawctxt = kzalloc(sizeof(struct adreno_context), GFP_KERNEL); if (drawctxt == NULL) return ERR_PTR(-ENOMEM); ret = kgsl_context_init(dev_priv, &drawctxt->base); if (ret != 0) { kfree(drawctxt); return ERR_PTR(ret); } drawctxt->timestamp = 0; drawctxt->base.flags = *flags & (KGSL_CONTEXT_PREAMBLE | KGSL_CONTEXT_NO_GMEM_ALLOC | KGSL_CONTEXT_PER_CONTEXT_TS | KGSL_CONTEXT_USER_GENERATED_TS | KGSL_CONTEXT_NO_FAULT_TOLERANCE | KGSL_CONTEXT_CTX_SWITCH | KGSL_CONTEXT_PRIORITY_MASK | KGSL_CONTEXT_TYPE_MASK | KGSL_CONTEXT_PWR_CONSTRAINT); /* Always enable per-context timestamps */ drawctxt->base.flags |= KGSL_CONTEXT_PER_CONTEXT_TS; drawctxt->type = (drawctxt->base.flags & KGSL_CONTEXT_TYPE_MASK) >> KGSL_CONTEXT_TYPE_SHIFT; mutex_init(&drawctxt->mutex); init_waitqueue_head(&drawctxt->wq); init_waitqueue_head(&drawctxt->waiting); /* Set the context priority */ _set_context_priority(drawctxt); /* * Set up the plist node for the dispatcher. Insert the node into the * drawctxt pending list based on priority. */ plist_node_init(&drawctxt->pending, drawctxt->base.priority); if ((drawctxt->base.flags & KGSL_CONTEXT_PREAMBLE) == 0 || (drawctxt->base.flags & KGSL_CONTEXT_NO_GMEM_ALLOC) == 0) { KGSL_DEV_ERR_ONCE(device, "legacy context switch not supported\n"); ret = -EINVAL; goto err; } kgsl_sharedmem_writel(device, &device->memstore, KGSL_MEMSTORE_OFFSET(drawctxt->base.id, soptimestamp), 0); kgsl_sharedmem_writel(device, &device->memstore, KGSL_MEMSTORE_OFFSET(drawctxt->base.id, eoptimestamp), 0); /* copy back whatever flags we dediced were valid */ *flags = drawctxt->base.flags; return &drawctxt->base; err: kgsl_context_detach(&drawctxt->base); return ERR_PTR(ret); }
/** * adreno_drawctxt_create - create a new adreno draw context * @dev_priv: the owner of the context * @flags: flags for the context (passed from user space) * * Create and return a new draw context for the 3D core. */ struct kgsl_context * adreno_drawctxt_create(struct kgsl_device_private *dev_priv, uint32_t *flags) { struct adreno_context *drawctxt; struct kgsl_device *device = dev_priv->device; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); int ret; unsigned long local; local = *flags & (KGSL_CONTEXT_PREAMBLE | KGSL_CONTEXT_NO_GMEM_ALLOC | KGSL_CONTEXT_PER_CONTEXT_TS | KGSL_CONTEXT_USER_GENERATED_TS | KGSL_CONTEXT_NO_FAULT_TOLERANCE | KGSL_CONTEXT_CTX_SWITCH | KGSL_CONTEXT_PRIORITY_MASK | KGSL_CONTEXT_TYPE_MASK | KGSL_CONTEXT_PWR_CONSTRAINT | KGSL_CONTEXT_IFH_NOP | KGSL_CONTEXT_SECURE); /* Check for errors before trying to initialize */ /* We no longer support legacy context switching */ if ((local & KGSL_CONTEXT_PREAMBLE) == 0 || (local & KGSL_CONTEXT_NO_GMEM_ALLOC) == 0) { KGSL_DEV_ERR_ONCE(device, "legacy context switch not supported\n"); return ERR_PTR(-EINVAL); } /* Make sure that our target can support secure contexts if requested */ if (!kgsl_mmu_is_secured(&dev_priv->device->mmu) && (local & KGSL_CONTEXT_SECURE)) { KGSL_DEV_ERR_ONCE(device, "Secure context not supported\n"); return ERR_PTR(-EINVAL); } drawctxt = kzalloc(sizeof(struct adreno_context), GFP_KERNEL); if (drawctxt == NULL) return ERR_PTR(-ENOMEM); ret = kgsl_context_init(dev_priv, &drawctxt->base); if (ret != 0) { kfree(drawctxt); return ERR_PTR(ret); } drawctxt->timestamp = 0; drawctxt->base.flags = local; /* Always enable per-context timestamps */ drawctxt->base.flags |= KGSL_CONTEXT_PER_CONTEXT_TS; drawctxt->type = (drawctxt->base.flags & KGSL_CONTEXT_TYPE_MASK) >> KGSL_CONTEXT_TYPE_SHIFT; spin_lock_init(&drawctxt->lock); init_waitqueue_head(&drawctxt->wq); init_waitqueue_head(&drawctxt->waiting); /* Set the context priority */ _set_context_priority(drawctxt); /* set the context ringbuffer */ drawctxt->rb = adreno_ctx_get_rb(adreno_dev, drawctxt); /* * Set up the plist node for the dispatcher. Insert the node into the * drawctxt pending list based on priority. */ plist_node_init(&drawctxt->pending, drawctxt->base.priority); kgsl_sharedmem_writel(device, &device->memstore, KGSL_MEMSTORE_OFFSET(drawctxt->base.id, soptimestamp), 0); kgsl_sharedmem_writel(device, &device->memstore, KGSL_MEMSTORE_OFFSET(drawctxt->base.id, eoptimestamp), 0); adreno_context_debugfs_init(ADRENO_DEVICE(device), drawctxt); /* copy back whatever flags we dediced were valid */ *flags = drawctxt->base.flags; return &drawctxt->base; }
static int __devinit sii9244_mhl_tx_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct sii9244_data *sii9244; int ret; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; sii9244 = kzalloc(sizeof(struct sii9244_data), GFP_KERNEL); if (!sii9244) { dev_err(&client->dev, "failed to allocate driver data\n"); return -ENOMEM; } sii9244->pdata = client->dev.platform_data; sii9244->pdata->mhl_tx_client = client; if (!sii9244->pdata) { ret = -EINVAL; goto err_exit1; } i2c_set_clientdata(client, sii9244); sii9244->irq = client->irq; init_waitqueue_head(&sii9244->wq); mutex_init(&sii9244->lock); #if !defined(CONFIG_MACH_LGE_CX2) //nthyunjin.yang 120526 MHL_1V8 is different with CX2. if (sii9244->mhl_reg == NULL) { struct regulator *mhl_reg; mhl_reg = regulator_get(&client->dev, "mhl_1v8"); if (IS_ERR(mhl_reg)) { dev_err(&client->dev, "can't get MHL 1.8V regulator\n"); return PTR_ERR(mhl_reg); } sii9244->mhl_reg = mhl_reg; } #endif ret = request_threaded_irq(client->irq, NULL, sii9244_irq_thread, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "sii9244", sii9244); if (ret < 0) goto err_exit2; disable_irq(client->irq); /* GPIO configuration */ sii9244_gpio_config(sii9244); #if defined(CONFIG_MUIC) /* Register detection/cancel func to MUIC driver */ ret = muic_client_dev_register(client->name, sii9244, &mhl_ops); if (ret < 0) { dev_err(&client->dev, "Unable to register mhl_ops\n"); goto err_exit2; } #else sii9244->otg_id_nb.detect = sii9244_detection_callback; sii9244->otg_id_nb.cancel = sii9244_cancel_callback; sii9244->otg_id_nb.priority = sii9244->pdata->prio; plist_node_init(&sii9244->otg_id_nb.p, sii9244->pdata->prio); ret = otg_id_register_notifier(&sii9244->otg_id_nb); if (ret < 0) { dev_err(&client->dev, "Unable to register notifier\n"); goto err_exit2; } #endif return 0; err_exit2: err_exit1: kfree(sii9244); return ret; }
struct kgsl_context * adreno_drawctxt_create(struct kgsl_device_private *dev_priv, uint32_t *flags) { struct adreno_context *drawctxt; struct kgsl_device *device = dev_priv->device; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); int ret; drawctxt = kzalloc(sizeof(struct adreno_context), GFP_KERNEL); if (drawctxt == NULL) return ERR_PTR(-ENOMEM); ret = kgsl_context_init(dev_priv, &drawctxt->base); if (ret != 0) { kfree(drawctxt); return ERR_PTR(ret); } drawctxt->bin_base_offset = 0; drawctxt->timestamp = 0; drawctxt->base.flags = *flags & (KGSL_CONTEXT_PREAMBLE | KGSL_CONTEXT_NO_GMEM_ALLOC | KGSL_CONTEXT_PER_CONTEXT_TS | KGSL_CONTEXT_USER_GENERATED_TS | KGSL_CONTEXT_NO_FAULT_TOLERANCE | KGSL_CONTEXT_TYPE_MASK); drawctxt->base.flags |= KGSL_CONTEXT_PER_CONTEXT_TS; drawctxt->type = (drawctxt->base.flags & KGSL_CONTEXT_TYPE_MASK) >> KGSL_CONTEXT_TYPE_SHIFT; mutex_init(&drawctxt->mutex); init_waitqueue_head(&drawctxt->wq); init_waitqueue_head(&drawctxt->waiting); plist_node_init(&drawctxt->pending, ADRENO_CONTEXT_DEFAULT_PRIORITY); if (adreno_dev->gpudev->ctxt_create) { ret = adreno_dev->gpudev->ctxt_create(adreno_dev, drawctxt); if (ret) goto err; } else if ((drawctxt->base.flags & KGSL_CONTEXT_PREAMBLE) == 0 || (drawctxt->base.flags & KGSL_CONTEXT_NO_GMEM_ALLOC) == 0) { KGSL_DEV_ERR_ONCE(device, "legacy context switch not supported\n"); ret = -EINVAL; goto err; } else { drawctxt->ops = &adreno_preamble_ctx_ops; } kgsl_sharedmem_writel(device, &device->memstore, KGSL_MEMSTORE_OFFSET(drawctxt->base.id, soptimestamp), 0); kgsl_sharedmem_writel(device, &device->memstore, KGSL_MEMSTORE_OFFSET(drawctxt->base.id, eoptimestamp), 0); *flags = drawctxt->base.flags; return &drawctxt->base; err: kgsl_context_detach(&drawctxt->base); return ERR_PTR(ret); }
/** * adreno_drawctxt_create - create a new adreno draw context * @dev_priv: the owner of the context * @flags: flags for the context (passed from user space) * * Create and return a new draw context for the 3D core. */ struct kgsl_context * adreno_drawctxt_create(struct kgsl_device_private *dev_priv, uint32_t *flags) { struct adreno_context *drawctxt; struct kgsl_device *device = dev_priv->device; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); int ret; drawctxt = kzalloc(sizeof(struct adreno_context), GFP_KERNEL); if (drawctxt == NULL) return ERR_PTR(-ENOMEM); ret = kgsl_context_init(dev_priv, &drawctxt->base); if (ret != 0) { kfree(drawctxt); return ERR_PTR(ret); } drawctxt->bin_base_offset = 0; drawctxt->timestamp = 0; drawctxt->base.flags = *flags & (KGSL_CONTEXT_PREAMBLE | KGSL_CONTEXT_NO_GMEM_ALLOC | KGSL_CONTEXT_PER_CONTEXT_TS | KGSL_CONTEXT_USER_GENERATED_TS | KGSL_CONTEXT_NO_FAULT_TOLERANCE | KGSL_CONTEXT_TYPE_MASK); /* Always enable per-context timestamps */ drawctxt->base.flags |= KGSL_CONTEXT_PER_CONTEXT_TS; mutex_init(&drawctxt->mutex); init_waitqueue_head(&drawctxt->wq); init_waitqueue_head(&drawctxt->waiting); /* * Set up the plist node for the dispatcher. For now all contexts have * the same priority, but later the priority will be set at create time * by the user */ plist_node_init(&drawctxt->pending, ADRENO_CONTEXT_DEFAULT_PRIORITY); if (adreno_dev->gpudev->ctxt_create) { ret = adreno_dev->gpudev->ctxt_create(adreno_dev, drawctxt); if (ret) goto err; } else if ((drawctxt->base.flags & KGSL_CONTEXT_PREAMBLE) == 0 || (drawctxt->base.flags & KGSL_CONTEXT_NO_GMEM_ALLOC) == 0) { KGSL_DEV_ERR_ONCE(device, "legacy context switch not supported\n"); ret = -EINVAL; goto err; } else { drawctxt->ops = &adreno_preamble_ctx_ops; } kgsl_sharedmem_writel(device, &device->memstore, KGSL_MEMSTORE_OFFSET(drawctxt->base.id, soptimestamp), 0); kgsl_sharedmem_writel(device, &device->memstore, KGSL_MEMSTORE_OFFSET(drawctxt->base.id, eoptimestamp), 0); /* copy back whatever flags we dediced were valid */ *flags = drawctxt->base.flags; return &drawctxt->base; err: kgsl_context_detach(&drawctxt->base); return ERR_PTR(ret); }
/* * Task blocks on lock. * * Prepare waiter and propagate pi chain * * This must be called with lock->wait_lock held. */ static int task_blocks_on_rt_mutex(struct rt_mutex *lock, struct rt_mutex_waiter *waiter, struct task_struct *task, int detect_deadlock) { struct task_struct *owner = rt_mutex_owner(lock); struct rt_mutex_waiter *top_waiter = waiter; unsigned long flags; int chain_walk = 0, res; /* * Early deadlock detection. We really don't want the task to * enqueue on itself just to untangle the mess later. It's not * only an optimization. We drop the locks, so another waiter * can come in before the chain walk detects the deadlock. So * the other will detect the deadlock and return -EDEADLOCK, * which is wrong, as the other waiter is not in a deadlock * situation. */ if (detect_deadlock && owner == task) return -EDEADLK; raw_spin_lock_irqsave(&task->pi_lock, flags); __rt_mutex_adjust_prio(task); waiter->task = task; waiter->lock = lock; plist_node_init(&waiter->list_entry, task->prio); plist_node_init(&waiter->pi_list_entry, task->prio); /* Get the top priority waiter on the lock */ if (rt_mutex_has_waiters(lock)) top_waiter = rt_mutex_top_waiter(lock); plist_add(&waiter->list_entry, &lock->wait_list); task->pi_blocked_on = waiter; raw_spin_unlock_irqrestore(&task->pi_lock, flags); if (!owner) return 0; if (waiter == rt_mutex_top_waiter(lock)) { raw_spin_lock_irqsave(&owner->pi_lock, flags); plist_del(&top_waiter->pi_list_entry, &owner->pi_waiters); plist_add(&waiter->pi_list_entry, &owner->pi_waiters); __rt_mutex_adjust_prio(owner); if (owner->pi_blocked_on) chain_walk = 1; raw_spin_unlock_irqrestore(&owner->pi_lock, flags); } else if (debug_rt_mutex_detect_deadlock(waiter, detect_deadlock)) chain_walk = 1; if (!chain_walk) return 0; /* * The owner can't disappear while holding a lock, * so the owner struct is protected by wait_lock. * Gets dropped in rt_mutex_adjust_prio_chain()! */ get_task_struct(owner); raw_spin_unlock(&lock->wait_lock); res = rt_mutex_adjust_prio_chain(owner, detect_deadlock, lock, waiter, task); raw_spin_lock(&lock->wait_lock); return res; }
/* * Task blocks on lock. * * Prepare waiter and propagate pi chain * * This must be called with lock->wait_lock held. */ static int task_blocks_on_rt_mutex(struct rt_mutex *lock, struct rt_mutex_waiter *waiter, struct task_struct *task, int detect_deadlock, unsigned long flags, int savestate) { struct task_struct *owner = rt_mutex_owner(lock); struct rt_mutex_waiter *top_waiter = waiter; int chain_walk = 0, res; raw_spin_lock(&task->pi_lock); /* * In the case of futex requeue PI, this will be a proxy * lock. The task will wake unaware that it is enqueueed on * this lock. Avoid blocking on two locks and corrupting * pi_blocked_on via the PI_WAKEUP_INPROGRESS * flag. futex_wait_requeue_pi() sets this when it wakes up * before requeue (due to a signal or timeout). Do not enqueue * the task if PI_WAKEUP_INPROGRESS is set. */ if (task != current && task->pi_blocked_on == PI_WAKEUP_INPROGRESS) { raw_spin_unlock(&task->pi_lock); return -EAGAIN; } BUG_ON(rt_mutex_real_waiter(task->pi_blocked_on)); __rt_mutex_adjust_prio(task); waiter->task = task; waiter->lock = lock; waiter->savestate = savestate; plist_node_init(&waiter->list_entry, task->prio); plist_node_init(&waiter->pi_list_entry, task->prio); /* Get the top priority waiter on the lock */ if (rt_mutex_has_waiters(lock)) top_waiter = rt_mutex_top_waiter(lock); plist_add(&waiter->list_entry, &lock->wait_list); task->pi_blocked_on = waiter; raw_spin_unlock(&task->pi_lock); if (!owner) return 0; if (waiter == rt_mutex_top_waiter(lock)) { raw_spin_lock(&owner->pi_lock); plist_del(&top_waiter->pi_list_entry, &owner->pi_waiters); plist_add(&waiter->pi_list_entry, &owner->pi_waiters); __rt_mutex_adjust_prio(owner); if (rt_mutex_real_waiter(owner->pi_blocked_on)) chain_walk = 1; raw_spin_unlock(&owner->pi_lock); } else if (debug_rt_mutex_detect_deadlock(waiter, detect_deadlock)) chain_walk = 1; if (!chain_walk) return 0; /* * The owner can't disappear while holding a lock, * so the owner struct is protected by wait_lock. * Gets dropped in rt_mutex_adjust_prio_chain()! */ get_task_struct(owner); raw_spin_unlock_irqrestore(&lock->wait_lock, flags); res = rt_mutex_adjust_prio_chain(owner, detect_deadlock, lock, waiter, task); raw_spin_lock_irq(&lock->wait_lock); return res; }