/*
 * Implementação de locks recursivos.
 */

typedef struct {
  int c;
  mutex_t mutex;
  pthread_t id;
  cond_t cond;
} rec_mutex_t;


int rec_mutex_init(rec_mutex_t* rec_m) {
  mutex_init(&rec_m->mutex);
  rec_m->c = 0;
  rec_m->id = 0;
  return 0;
}

int rec_mutex_lock(rec_mutex_t* rec_m) {
  mutex_lock(&rec_m->mutex);
  if (rec_m->id == pthread_self())
    rec_m->c++;
  else {
    while (rec_m->c != 0)
      cond_wait(&rec_m->cond, &rec_m->mutex);
    rec_m->id = pthread_self();
    rec_m->c = 1;
  }
  mutex_unlock(&rec_m->mutex);
  return 0;
}

int rec_mutex_unlock(rec_mutex_t* rec_m) {
  mutex_lock(&rec_m->mutex);
  if (rec_m->id != pthread_self()) {
    mutex_unlock(&rec_m->mutex);
    return -1;
  }
  if (rec_m->c == 0) {
    mutex_unlock(&rec_m->mutex);
    return -1;
  }
  rec_m->c--;
  if (rec_m->c == 0)
    cond_signal(&rec_m->cond);
  mutex_unlock(&rec_m->mutex);
  return 0;
}

int rec_mutex_destroy(rec_mutex_t* rec_m) {
  return 0;
}