Skip to content

Instantly share code, notes, and snippets.

@deadtrickster
Last active October 10, 2016 09:04
Show Gist options
  • Save deadtrickster/1576f2e4e60f106a3fd51ae6f66855a8 to your computer and use it in GitHub Desktop.
Save deadtrickster/1576f2e4e60f106a3fd51ae6f66855a8 to your computer and use it in GitHub Desktop.
(with-pinned-objects (queue me)
(setf (waitqueue-token queue) me)
(release-mutex mutex)
;; Now we go to sleep using futex-wait. If anyone else
;; manages to grab MUTEX and call CONDITION-NOTIFY during
;; this comment, it will change the token, and so futex-wait
;; returns immediately instead of sleeping. Ergo, no lost
;; wakeup. We may get spurious wakeups, but that's ok.
(setf status
(case (allow-with-interrupts
(futex-wait (waitqueue-token-address queue)
(get-lisp-obj-address me)
;; our way of saying "no
;; timeout":
(or to-sec -1)
(or to-usec 0)))
((1)
;; 1 = ETIMEDOUT
:timeout)
(t
;; -1 = EWOULDBLOCK, possibly spurious wakeup
;; 0 = normal wakeup
;; 2 = EINTR, a spurious wakeup
:ok))))
static inline int sys_futex(void *futex, int op, int val, struct timespec *rel)
{
return syscall(SYS_futex, futex, op, val, rel);
}
int
futex_wait(int *lock_word, int oldval, long sec, unsigned long usec)
{
struct timespec timeout;
int t;
if (sec<0) {
t = sys_futex(lock_word, futex_wait_op(), oldval, 0);
}
else {
timeout.tv_sec = sec;
timeout.tv_nsec = usec * 1000;
t = sys_futex(lock_word, futex_wait_op(), oldval, &timeout);
}
if (t==0)
return 0;
else if (errno==ETIMEDOUT)
return 1;
else if (errno==EINTR)
return 2;
else
/* EWOULDBLOCK and others, need to check the lock */
return -1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment