6

How can unrelated processes cooperate using a futex?

Let's say I have unrelated processes, one being, say, an apache subprocess with my module, another being e.g. a background script.

I'd like to establish a condition variable with a mutex between the two using a futex, to benefit for user-space fast code path.

It seems to me that memory at which mutex is stored could be in a mmap'd file, if that memory is mapped, e.g. mlock'd the two processes could theoretically issue futex calls against same address.

Alternatively, perhaps a futex can be passed from one process to another using FUTEX_FD.

Code submissions low-, high-level and dynamic languages are accepted (C, C++, Python, etc.). "robust futex" API must be supported too.

References:

Dima Tisnek
  • 11,241
  • 4
  • 68
  • 120
  • P.S. If this cannot be done, please explain in detail why. – Dima Tisnek Feb 12 '16 at 07:40
  • 1
    The [manpage says](http://man7.org/linux/man-pages/man7/pthreads.7.html) that pthreads uses futexes internally. Did you consider to simply use the high level API (as the [futex manpage recommends](http://man7.org/linux/man-pages/man7/futex.7.html)), and use a pthread condition with `PTHREAD_PROCESS_SHARED`? – Phillip Feb 12 '16 at 09:34
  • have you checked this http://locklessinc.com/articles/mutex_cv_futex/ – Ghayel Feb 12 '16 at 15:30
  • @Ghayel yes I did, it's listed in the question. – Dima Tisnek Feb 15 '16 at 08:45
  • @Phillip looks like http://linux.die.net/man/3/pthread_mutexattr_init has an example code that in fact sets up a futex in a `mmap`ed without common `fork` parent. Good hint! – Dima Tisnek Feb 15 '16 at 08:57
  • From http://man7.org/linux/man-pages/man2/futex.2.html In order to share a futex between processes, the futex is placed in a region of shared memory, created using (for example) mmap(2) or shmat(2). Should not be difficult to implement. – Felix M. Feb 18 '16 at 15:10

2 Answers2

0

mutex are defined to lock access to shared resources. This does not seem what you want to do .

if you want both process to cooperate, you may either use shared mmap area, or semaphore

sancelot
  • 1,905
  • 12
  • 31
0

Thanks Phillip and Felix M. for pointers.

Python user code (file with data structures already exists, initialised with PTHREAD_PROCESS_SHARED)

with open("/tmp/semaphore", "rb+") as f:
    m = mmap.mmap(f.fileno(), 0)  # default: all file, share, read-write

data = ffi.cast("unsigned long[3]", id(m))[2]  # pointer to mapped area, 64-bit CPython
lock = ffi.cast("pthread_mutex_t *", data)
cond = ffi.cast("pthread_cond_t *", data + 40)

@contextlib.contextmanager
def locked(alock):
    assert not C.pthread_mutex_lock(alock)
    try:
        yield
    finally:
        assert not C.pthread_mutex_unlock(alock)

Wait and get awoken:

if "wait" in sys.argv:
    with locked(lock):
        assert not C.pthread_cond_wait(cond, lock)

elif "signal" in sys.argv:
    with locked(lock):
        assert not C.pthread_cond_signal(cond)

Basics of setting PTHREAD_PROCESS_SHARED:

l = ffi.new("pthread_mutexattr_t *")
assert not C.pthread_mutexattr_init(l)
assert not C.pthread_mutexattr_setpshared(l, 1)  # PTHREAD_PROCESS_SHARED
assert not C.pthread_mutex_init(lock, l)
# same for condition variable

Full code for nitpicks :-) https://github.com/dimaqq/pthread_mutexattr_init/blob/master/xsem.py based on http://linux.die.net/man/3/pthread_mutexattr_init

Community
  • 1
  • 1
Dima Tisnek
  • 11,241
  • 4
  • 68
  • 120