Logo Search packages:      
Sourcecode: jmp version File versions  Download package

deadlock_detector.c

#include <stdio.h>
#include <stdlib.h>
#include <jmp.h>
#include <jthread.h>
#include <heap_dump.h>
#include <deadlock_detector.h>
#include <ui.h>

typedef struct deadlock_info {
    jthread* t;
    void* id;
    monitor_info* mi;
} deadlock_info;

typedef struct deadlock_detector {
    hashtab*         monitors;
    visited_threads* threads;
    int              found;
} deadlock_detector;

static void find_t_waiting_for_enter (monitor_info* mi, deadlock_info* di) {
    int i;
    if (di->id != NULL)
      return;
    for (i = 0; i < mi->num_waiting_to_enter; i++) {
      if (mi->waiting_to_enter[i] == di->t) {
          di->id = mi->id;
          di->t = mi->owner;
          di->mi = mi;
          break;
      }
    }
}

static deadlock_info trying_to_enter (jthread* t, hashtab* monitors) {
    deadlock_info di;
    di.t = t;
    di.id = NULL;
    jmphash_for_each_with_arg ((jmphash_iter_fa)find_t_waiting_for_enter, 
                         monitors, &di);
    return di;
}

static int already_visited (jthread* t, visited_threads* vt) {
    while (vt != NULL && vt->mi->owner != t) 
      vt = vt->next;
    return vt != NULL;
}

static void visit (monitor_info* mi, deadlock_detector* dd) {
    visited_threads* vt = calloc (1, sizeof (*vt));
    // TODO: handle NULL
    vt->mi = mi;
    vt->next = dd->threads;
    dd->threads = vt;
}

static void detect_monitor_deadlocked (monitor_info* mi, deadlock_detector* dd) {
    void* id = mi->id;
    deadlock_info di;
    jthread* t = mi->owner;
    if (dd->found) 
      return;
    if (t == NULL)
      return;    
    if (already_visited (t, dd->threads))
      return;
    visit (mi, dd);
    di = trying_to_enter (t, dd->monitors);
    while (di.id != NULL) {
      visit (di.mi, dd);
      if (di.id != NULL && di.id == id) {
          dd->found = 1;
          break;
      }
      di = trying_to_enter (di.t, dd->monitors);
    }
}

void detect_deadlock (hashtab* monitors) {
    deadlock_detector dd;
    visited_threads* vt;
    visited_threads* vtn;
    dd.monitors = monitors;
    dd.threads = NULL;
    dd.found = 0;
    jmphash_for_each_with_arg ((jmphash_iter_fa)detect_monitor_deadlocked, 
                         monitors, &dd);
    vt = dd.threads;
    if (dd.found) {
      show_deadlock (vt);
    }
    while (vt != NULL) {
      vtn = vt->next;
      free (vt);
      vt = vtn;
    }
}

/* Emacs Local Variables: */
/* Emacs mode:C */
/* Emacs c-indentation-style:"gnu" */
/* Emacs c-hanging-braces-alist:((brace-list-open)(brace-entry-open)(defun-open after)(substatement-open after)(block-close . c-snug-do-while)(extern-lang-open after)) */
/* Emacs c-cleanup-list:(brace-else-brace brace-elseif-brace space-before-funcall) */
/* Emacs c-basic-offset:4 */
/* Emacs End: */

Generated by  Doxygen 1.6.0   Back to index