in vboxguest/vboxguest_core.c [825:866]
static int vbg_set_session_capabilities(struct vbg_dev *gdev,
struct vbg_session *session,
u32 or_mask, u32 not_mask,
bool session_termination)
{
u32 changed, previous;
int ret = 0;
mutex_lock(&gdev->session_mutex);
if (gdev->acquire_mode_guest_caps & or_mask) {
vbg_err("%s error: cannot set caps which are in acquire_mode\n",
__func__);
ret = -EBUSY;
goto out;
}
/* Apply the changes to the session mask. */
previous = session->set_guest_caps;
session->set_guest_caps |= or_mask;
session->set_guest_caps &= ~not_mask;
/* If anything actually changed, update the global usage counters. */
changed = previous ^ session->set_guest_caps;
if (!changed)
goto out;
vbg_track_bit_usage(&gdev->set_guest_caps_tracker, changed, previous);
ret = vbg_set_host_capabilities(gdev, session, session_termination);
/* Roll back on failure, unless it's session termination time. */
if (ret < 0 && !session_termination) {
vbg_track_bit_usage(&gdev->set_guest_caps_tracker, changed,
session->set_guest_caps);
session->set_guest_caps = previous;
}
out:
mutex_unlock(&gdev->session_mutex);
return ret;
}