/* * Return values: * 0 : try and take the lock again in local memory * -ret: return -ret */ int lock_take_contention(cos_lock_t *l, union cos_lock_atomic_struct *result, union cos_lock_atomic_struct *prev_val, u16_t owner) { int lock_id = l->lock_id; spdid_t spdid = cos_spd_id(); int ret; if (lock_component_pretake(spdid, lock_id, owner)) return -1; /* Must access memory (be volatile) as we want * to detect changes here */ if (owner != l->atom.c.owner) return 0; /* Mark the lock as contested */ if (!l->atom.c.contested) { result->c.contested = 1; result->c.owner = owner; if (!cos_cas((unsigned long*)&l->atom.v, prev_val->v, result->v)) return 0; assert(l->atom.c.contested); } /* Note if a 1 is returned, there is a * generation mismatch, and we just want to * try and take the lock again anyway */ ret = lock_component_take(spdid, lock_id, owner); return ret < 0 ? ret : 0; }
static inline int block_ser_if_block_track_lock_component_take(spdid_t spdid, ul_t lock_id, u32_t thd_id) { int ret = 0; struct track_block tb; // track on stack do { if (sched_component_take(cos_spd_id())) BUG(); } while (0); if (unlikely(!tracking_block_list[spdid].next)) { INIT_LIST(&tracking_block_list[spdid], next, prev); } INIT_LIST(&tb, next, prev); tb.lock_id = lock_id; ADD_LIST(&tracking_block_list[spdid], &tb, next, prev); do { if (sched_component_release(cos_spd_id())) BUG(); } while (0); ret = lock_component_take(spdid, lock_id, thd_id); do { if (sched_component_take(cos_spd_id())) BUG(); } while (0); REM_LIST(&tb, next, prev); do { if (sched_component_release(cos_spd_id())) BUG(); } while (0); return ret; }