Changeset 7547


Ignore:
Timestamp:
Oct 29, 2007, 6:50:04 AM (12 years ago)
Author:
gb
Message:

Optionally, use futexes instead of spinlocks when USE_FUTEX is defined.

Log TCR activity via syslog if the environment variable "LOG_TCR_INFO"
is set (value doesn't matter, empty string is OK) on startup.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/working-0710/ccl/lisp-kernel/thread_manager.c

    r7527 r7547  
    3838#endif
    3939
     40void
     41log_tcr_initialization(TCR *tcr) {
     42  syslog((LOG_USER|LOG_INFO), "created tcr at 0x%lx for thread 0x%lx", tcr, pthread_self());
     43}
     44
     45void
     46log_tcr_access(TCR *tcr) {
     47  syslog((LOG_USER|LOG_INFO), "accessed tcr at 0x%lx from thread 0x%lx", tcr, pthread_self());
     48}
     49
     50void
     51log_tcr_exit(TCR *tcr) {
     52  syslog((LOG_USER|LOG_INFO), "thread 0x%lx exiting, had tcr 0x%lx", pthread_self(), tcr);
     53}
     54
    4055extern natural
    4156store_conditional(natural*, natural, natural);
     
    4459atomic_swap(signed_natural*, signed_natural);
    4560
     61#ifdef USE_FUTEX
     62#define futex_wait(futex,val) syscall(SYS_futex,futex,FUTEX_WAIT,val)
     63#define futex_wake(futex,n) syscall(SYS_futex,futex,FUTEX_WAKE,n)
     64#define FUTEX_AVAIL (0)
     65#define FUTEX_LOCKED (1)
     66#define FUTEX_CONTENDED (2)
     67#endif
    4668
    4769int
     
    87109
    88110
     111#ifndef USE_FUTEX
    89112int spin_lock_tries = 1;
    90113
     
    103126  }
    104127}
    105 
    106 
     128#endif
     129
     130#ifndef USE_FUTEX
    107131int
    108132lock_recursive_lock(RECURSIVE_LOCK m, TCR *tcr)
     
    131155}
    132156
    133  
     157#else /* USE_FUTEX */
     158
     159static void inline
     160lock_futex(natural *p)
     161{
     162 
     163  while (1) {
     164    if (store_conditional(p,FUTEX_AVAIL,FUTEX_LOCKED) == FUTEX_AVAIL) {
     165      return;
     166    }
     167    while (1) {
     168      if (atomic_swap(p,FUTEX_CONTENDED) == FUTEX_AVAIL) {
     169        return;
     170      }
     171      futex_wait(p,FUTEX_CONTENDED);
     172    }
     173  }
     174}
     175
     176static void inline
     177unlock_futex(natural *p)
     178{
     179  if (atomic_decf(p) != FUTEX_AVAIL) {
     180    *p = FUTEX_AVAIL;
     181    futex_wake(p,INT_MAX);
     182  }
     183}
     184   
     185int
     186lock_recursive_lock(RECURSIVE_LOCK m, TCR *tcr)
     187{
     188  natural val;
     189  if (tcr == NULL) {
     190    tcr = get_tcr(true);
     191  }
     192  if (m->owner == tcr) {
     193    m->count++;
     194    return 0;
     195  }
     196  lock_futex(&m->avail);
     197  m->owner = tcr;
     198  m->count = 1;
     199  return 0;
     200}
     201#endif /* USE_FUTEX */
     202
     203
     204#ifndef USE_FUTEX 
    134205int
    135206unlock_recursive_lock(RECURSIVE_LOCK m, TCR *tcr)
     
    163234  return ret;
    164235}
     236#else /* USE_FUTEX */
     237int
     238unlock_recursive_lock(RECURSIVE_LOCK m, TCR *tcr)
     239{
     240  int ret = EPERM, pending;
     241
     242   if (tcr == NULL) {
     243    tcr = get_tcr(true);
     244  }
     245
     246  if (m->owner == tcr) {
     247    --m->count;
     248    if (m->count == 0) {
     249      m->owner = NULL;
     250      unlock_futex(&m->avail);
     251    }
     252    ret = 0;
     253  }
     254  return ret;
     255}
     256#endif /* USE_FUTEX */
    165257
    166258void
    167259destroy_recursive_lock(RECURSIVE_LOCK m)
    168260{
     261#ifndef USE_FUTEX
    169262  destroy_semaphore((void **)&m->signal);
     263#endif
    170264  postGCfree((void *)(m->malloced_ptr));
    171265}
     
    177271*/
    178272
     273#ifndef USE_FUTEX
    179274int
    180275recursive_lock_trylock(RECURSIVE_LOCK m, TCR *tcr, int *was_free)
     
    204299  return EBUSY;
    205300}
     301#else
     302int
     303recursive_lock_trylock(RECURSIVE_LOCK m, TCR *tcr, int *was_free)
     304{
     305  TCR *owner = m->owner;
     306
     307  if (owner == tcr) {
     308    m->count++;
     309    if (was_free) {
     310      *was_free = 0;
     311      return 0;
     312    }
     313  }
     314  if (store_conditional((natural*)&(m->avail), 0, 1) == 0) {
     315    m->owner = tcr;
     316    m->count = 1;
     317    if (was_free) {
     318      *was_free = 1;
     319    }
     320    return 0;
     321  }
     322
     323  return EBUSY;
     324}
     325#endif
    206326
    207327void
     
    425545  void *p = calloc(1,sizeof(_recursive_lock)+cache_block_size-1);
    426546  RECURSIVE_LOCK m = NULL;
     547#ifndef USE_FUTEX
    427548  void *signal = new_semaphore(0);
     549#endif
    428550
    429551  if (p) {
     
    432554  }
    433555
     556#ifdef USE_FUTEX
     557  if (m) {
     558    return m;
     559  }
     560#else
    434561  if (m && signal) {
    435562    m->signal = signal;
     
    442569    destroy_semaphore(&signal);
    443570  }
     571#endif
    444572  return NULL;
    445573}
     
    696824    dequeue_tcr(tcr);
    697825#endif
     826    if (log_tcr_info) {
     827      log_tcr_exit(tcr);
     828    }
    698829    UNLOCK(lisp_global(TCR_AREA_LOCK),tcr);
    699830    if (termination_semaphore) {
     
    783914#endif
    784915  tcr->log2_allocation_quantum = unbox_fixnum(lisp_global(DEFAULT_ALLOCATION_QUANTUM));
     916  if (log_tcr_info) {
     917    log_tcr_initialization(tcr);
     918  }
    785919}
    786920
     
    843977Boolean threads_initialized = false;
    844978
     979#ifndef USE_FUTEX
    845980void
    846981count_cpus()
     
    8661001#endif
    8671002}
     1003#endif
     1004
     1005Boolean log_tcr_info = false;
    8681006
    8691007void
     
    8731011  pthread_key_create((pthread_key_t *)&(lisp_global(TCR_KEY)), shutdown_thread_tcr);
    8741012  thread_signal_setup();
     1013  if (getenv("LOG_TCR_INFO")) {
     1014    extern char *real_executable_name;
     1015    log_tcr_info = true;
     1016    openlog(real_executable_name, LOG_PID, LOG_USER);
     1017  }
     1018#ifndef USE_FUTEX
    8751019  count_cpus();
     1020#endif
    8761021  threads_initialized = true;
    8771022}
     
    10551200
    10561201  }
    1057  
     1202  if (log_tcr_info) {
     1203    log_tcr_access(current);
     1204  }
    10581205  return current;
    10591206}
     
    13631510    rw = (rwlock *) ((((natural)p)+cache_block_size-1) & (~(cache_block_size-1)));
    13641511    rw->malloced_ptr = p;
     1512#ifndef USE_FUTEX
    13651513    rw->reader_signal = new_semaphore(0);
    13661514    rw->writer_signal = new_semaphore(0);
     
    13741522      rw = NULL;
    13751523    }
     1524#endif
    13761525  }
    13771526  return rw;
     
    13871536  hold read access once.
    13881537*/
     1538#ifndef USE_FUTEX
    13891539int
    13901540rwlock_rlock(rwlock *rw, TCR *tcr, struct timespec *waitfor)
     
    14171567  return err;
    14181568}
    1419 
     1569#else
     1570int
     1571rwlock_rlock(rwlock *rw, TCR *tcr, struct timespec *waitfor)
     1572{
     1573  natural waitval;
     1574
     1575  lock_futex(&rw->spin);
     1576
     1577  if (rw->writer == tcr) {
     1578    unlock_futex(&rw->spin);
     1579    return EDEADLOCK;
     1580  }
     1581  while (1) {
     1582    if (rw->writer == NULL) {
     1583      --rw->state;
     1584      unlock_futex(&rw->spin);
     1585      return 0;
     1586    }
     1587    rw->blocked_readers++;
     1588    waitval = rw->reader_signal;
     1589    unlock_futex(&rw->spin);
     1590    futex_wait(&rw->reader_signal,waitval);
     1591    lock_futex(&rw->spin);
     1592    rw->blocked_readers--;
     1593  }
     1594  return 0;
     1595}
     1596#endif   
    14201597
    14211598
     
    14301607*/
    14311608
     1609#ifndef USE_FUTEX
    14321610int
    14331611rwlock_wlock(rwlock *rw, TCR *tcr, struct timespec *waitfor)
     
    14621640}
    14631641
     1642#else
     1643int
     1644rwlock_wlock(rwlock *rw, TCR *tcr, struct timespec *waitfor)
     1645{
     1646  int err = 0;
     1647  natural waitval;
     1648
     1649  lock_futex(&rw->spin);
     1650  if (rw->writer == tcr) {
     1651    rw->state++;
     1652    unlock_futex(&rw->spin);
     1653    return 0;
     1654  }
     1655
     1656  while (rw->state != 0) {
     1657    rw->blocked_writers++;
     1658    waitval = rw->writer_signal;
     1659    unlock_futex(&rw->spin);
     1660    futex_wait(&rw->writer_signal,waitval);
     1661    lock_futex(&rw->spin);
     1662    rw->blocked_writers--;
     1663  }
     1664  rw->state = 1;
     1665  rw->writer = tcr;
     1666  unlock_futex(&rw->spin);
     1667  return err;
     1668}
     1669#endif
     1670
    14641671/*
    14651672  Sort of the same as above, only return EBUSY if we'd have to wait.
    14661673*/
     1674#ifndef USE_FUTEX
    14671675int
    14681676rwlock_try_wlock(rwlock *rw, TCR *tcr)
     
    14841692  return ret;
    14851693}
    1486 
     1694#else
     1695int
     1696rwlock_try_wlock(rwlock *rw, TCR *tcr)
     1697{
     1698  int ret = EBUSY;
     1699
     1700  lock_futex(&rw->spin);
     1701  if (rw->writer == tcr) {
     1702    rw->state++;
     1703    ret = 0;
     1704  } else {
     1705    if (rw->state == 0) {
     1706      rw->writer = tcr;
     1707      rw->state = 1;
     1708      ret = 0;
     1709    }
     1710  }
     1711  unlock_futex(&rw->spin);
     1712  return ret;
     1713}
     1714#endif
     1715
     1716#ifndef USE_FUTEX
    14871717int
    14881718rwlock_try_rlock(rwlock *rw, TCR *tcr)
     
    14981728  return ret;
    14991729}
    1500 
    1501 
    1502 
     1730#else
     1731int
     1732rwlock_try_rlock(rwlock *rw, TCR *tcr)
     1733{
     1734  int ret = EBUSY;
     1735
     1736  lock_futex(&rw->spin);
     1737  if (rw->state <= 0) {
     1738    --rw->state;
     1739    ret = 0;
     1740  }
     1741  unlock_futex(&rw->spin);
     1742  return ret;
     1743}
     1744#endif
     1745
     1746
     1747
     1748#ifndef USE_FUTEX
    15031749int
    15041750rwlock_unlock(rwlock *rw, TCR *tcr)
     
    15141760    } else {
    15151761      --rw->state;
     1762      if (rw->state == 0) {
     1763        rw->writer = NULL;
     1764      }
    15161765    }
    15171766  } else {
     
    15401789  return 0;
    15411790}
     1791#else
     1792int
     1793rwlock_unlock(rwlock *rw, TCR *tcr)
     1794{
     1795
     1796  int err = 0;
     1797
     1798  lock_futex(&rw->spin);
     1799  if (rw->state > 0) {
     1800    if (rw->writer != tcr) {
     1801      err = EINVAL;
     1802    } else {
     1803      --rw->state;
     1804      if (rw->state == 0) {
     1805        rw->writer = NULL;
     1806      }
     1807    }
     1808  } else {
     1809    if (rw->state < 0) {
     1810      ++rw->state;
     1811    } else {
     1812      err = EINVAL;
     1813    }
     1814  }
     1815  if (err) {
     1816    unlock_futex(&rw->spin);
     1817    return err;
     1818  }
     1819 
     1820  if (rw->state == 0) {
     1821    if (rw->blocked_writers) {
     1822      ++rw->writer_signal;
     1823      unlock_futex(&rw->spin);
     1824      futex_wake(&rw->writer_signal,1);
     1825      return 0;
     1826    }
     1827    if (rw->blocked_readers) {
     1828      ++rw->reader_signal;
     1829      unlock_futex(&rw->spin);
     1830      futex_wake(&rw->reader_signal, INT_MAX);
     1831      return 0;
     1832    }
     1833  }
     1834  unlock_futex(&rw->spin);
     1835  return 0;
     1836}
     1837#endif
    15421838
    15431839       
     
    15451841rwlock_destroy(rwlock *rw)
    15461842{
     1843#ifndef USE_FUTEX
    15471844  destroy_semaphore((void **)&rw->reader_signal);
    15481845  destroy_semaphore((void **)&rw->writer_signal);
     1846#endif
    15491847  postGCfree((void *)(rw->malloced_ptr));
    15501848}
Note: See TracChangeset for help on using the changeset viewer.