Возможно ли "утверждать, что я держу этот мьютекс заблокированным"? - PullRequest
0 голосов
/ 26 декабря 2011

In Инструменты, с которыми мы работаем Автор программного обеспечения Varnish выразил разочарование по поводу нового проекта стандарта ISO C.Особенно он думает, что должно быть что-то полезное, например, «утверждаю, что я держу этот мьютекс заблокированным», и утверждает, что написал его на Vanish.

Я проверил код.По сути, это так:

struct ilck {
    unsigned        magic;
    pthread_mutex_t     mtx;
    int         held;
    pthread_t       owner;
    VTAILQ_ENTRY(ilck)  list;
    const char      *w;
    struct VSC_C_lck    *stat;
};


void Lck__Lock(struct ilck *ilck, const char *p, const char *f, int l)
{
    if (!(params->diag_bitmap & 0x18)) {
        AZ(pthread_mutex_lock(&ilck->mtx));
        AZ(ilck->held);
        ilck->stat->locks++;
        ilck->owner = pthread_self();
        ilck->held = 1;
        return;
    }
    r = pthread_mutex_trylock(&ilck->mtx);
    assert(r == 0 || r == EBUSY);
    if (r) {
        ilck->stat->colls++;
        if (params->diag_bitmap & 0x8)
            VSL(SLT_Debug, 0, "MTX_CONTEST(%s,%s,%d,%s)",
                p, f, l, ilck->w);
        AZ(pthread_mutex_lock(&ilck->mtx));
    } else if (params->diag_bitmap & 0x8) {
        VSL(SLT_Debug, 0, "MTX_LOCK(%s,%s,%d,%s)", p, f, l, ilck->w);
    }
    ilck->stat->locks++;
    ilck->owner = pthread_self();
    ilck->held = 1;
}

void
Lck__Assert(const struct ilck *ilck, int held)
{
    if (held)
        assert(ilck->held &&
            pthread_equal(ilck->owner, pthread_self()));
    else
        assert(!ilck->held ||
            !pthread_equal(ilck->owner, pthread_self()));
}

Я опускаю реализацию операций try-lock и unlock, поскольку они в основном рутинны.Место, где у меня есть вопрос, это Lck__Assert (), в котором доступ к ilck-> удерживается и lick-> owner не защищен никаким мьютексом.

Так скажем следующую последовательность событий:

  1. Нить A блокирует мьютекс.
  2. Нить A разблокирует его.
  3. Нить B блокирует тот же мьютекс.В процессе блокировки (в Lck_lock ()) поток B прерывается после обновления ilck-> hold, но до обновления ilck-> owner.Это должно быть возможно из-за того, что оптимизатор и процессор вышли из строя.
  4. Поток A запускается и вызывает Lck__Assert (), утверждение будет истинным, а поток A фактически не будет содержать мьютекс.

По моему мнению, должен существовать некоторый "глобальный" мьютекс для защиты его собственных данных или, по крайней мере, некоторый барьер записи / чтения.Является ли мой анализ правильным?

1 Ответ

0 голосов
/ 28 декабря 2011

Я связался с автором.Он говорит, что мой анализ действителен и использует memset (, 0,) для сброса «владельца thread_t», так как thread_t не является прозрачной структурой с указанным оператором присваивания.Надеюсь, что это работает на большинстве платформ.

...