LCK_GRP_DECLARE(coalitions_lck_grp, "coalition");
/* coalitions_list_lock protects coalition_count, coalitions queue, next_coalition_id. */
-static LCK_MTX_DECLARE(coalitions_list_lock, &coalitions_lck_grp);
+static LCK_RW_DECLARE(coalitions_list_lock, &coalitions_lck_grp);
static uint64_t coalition_count;
static uint64_t coalition_next_id = 1;
static queue_head_t coalitions_q;
lck_mtx_init(&new_coal->lock, &coalitions_lck_grp, LCK_ATTR_NULL);
- lck_mtx_lock(&coalitions_list_lock);
+ lck_rw_lock_exclusive(&coalitions_list_lock);
new_coal->id = coalition_next_id++;
coalition_count++;
enqueue_tail(&coalitions_q, &new_coal->coalitions);
#endif
cid = new_coal->id;
ctype = new_coal->type;
- lck_mtx_unlock(&coalitions_list_lock);
+ lck_rw_unlock_exclusive(&coalitions_list_lock);
coal_dbg("id:%llu, type:%s", cid, coal_type_str(ctype));
* coalition_find_by_id_internal
* Returns: Coalition object with specified id, NOT referenced.
* If not found, returns COALITION_NULL.
- * Condition: coalitions_list_lock must be LOCKED.
+ * If found, returns a locked coalition.
+ *
+ * Condition: No locks held
*/
static coalition_t
coalition_find_by_id_internal(uint64_t coal_id)
{
+ coalition_t coal;
+
if (coal_id == 0) {
return COALITION_NULL;
}
- lck_mtx_assert(&coalitions_list_lock, LCK_MTX_ASSERT_OWNED);
- coalition_t coal;
+ lck_rw_lock_shared(&coalitions_list_lock);
qe_foreach_element(coal, &coalitions_q, coalitions) {
if (coal->id == coal_id) {
+ coalition_lock(coal);
+ lck_rw_unlock_shared(&coalitions_list_lock);
return coal;
}
}
+ lck_rw_unlock_shared(&coalitions_list_lock);
+
return COALITION_NULL;
}
coalition_t
coalition_find_by_id(uint64_t cid)
{
- if (cid == 0) {
- return COALITION_NULL;
- }
-
- lck_mtx_lock(&coalitions_list_lock);
-
coalition_t coal = coalition_find_by_id_internal(cid);
+
if (coal == COALITION_NULL) {
- lck_mtx_unlock(&coalitions_list_lock);
return COALITION_NULL;
}
- coalition_lock(coal);
+ /* coal is locked */
if (coal->reaped) {
coalition_unlock(coal);
- lck_mtx_unlock(&coalitions_list_lock);
return COALITION_NULL;
}
#endif
coalition_unlock(coal);
- lck_mtx_unlock(&coalitions_list_lock);
coal_dbg("id:%llu type:%s ref_count:%u",
coal->id, coal_type_str(coal->type), rc);
coalition_t
coalition_find_and_activate_by_id(uint64_t cid)
{
- if (cid == 0) {
- return COALITION_NULL;
- }
-
- lck_mtx_lock(&coalitions_list_lock);
-
coalition_t coal = coalition_find_by_id_internal(cid);
+
if (coal == COALITION_NULL) {
- lck_mtx_unlock(&coalitions_list_lock);
return COALITION_NULL;
}
- coalition_lock(coal);
+ /* coal is locked */
if (coal->reaped || coal->terminated) {
/* Too late to put something new into this coalition, it's
* already on its way out the door */
coalition_unlock(coal);
- lck_mtx_unlock(&coalitions_list_lock);
return COALITION_NULL;
}
#endif
coalition_unlock(coal);
- lck_mtx_unlock(&coalitions_list_lock);
coal_dbg("id:%llu type:%s ref_count:%u, active_count:%u",
coal->id, coal_type_str(coal->type), rc, ac);
coalition_unlock(coal);
- lck_mtx_lock(&coalitions_list_lock);
+ lck_rw_lock_exclusive(&coalitions_list_lock);
coalition_count--;
remqueue(&coal->coalitions);
- lck_mtx_unlock(&coalitions_list_lock);
+ lck_rw_unlock_exclusive(&coalitions_list_lock);
/* Release the list's reference and launchd's reference. */
coalition_release(coal);
int ncoals = 0;
struct coalition *coal;
- lck_mtx_lock(&coalitions_list_lock);
+ lck_rw_lock_shared(&coalitions_list_lock);
qe_foreach_element(coal, &coalitions_q, coalitions) {
if (!coal->reaped && (type < 0 || type == (int)coal->type)) {
if (coal_list && ncoals < list_sz) {
++ncoals;
}
}
- lck_mtx_unlock(&coalitions_list_lock);
+ lck_rw_unlock_shared(&coalitions_list_lock);
return ncoals;
}