mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-01 00:38:31 +00:00
Share file offset across processes
This change ensures that if a file descriptor for an open disk file gets shared by multiple processes within a process tree, then lseek() changes will be visible across processes, and read() / write() are synchronized. Note this only applies to Windows, because UNIX kernels already do this.
This commit is contained in:
parent
a80ab3f8fe
commit
761c6ad615
15 changed files with 256 additions and 63 deletions
|
@ -16,13 +16,13 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/fds.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/ttydefaults.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/extend.h"
|
||||
#include "libc/intrin/fds.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/nomultics.h"
|
||||
#include "libc/intrin/pushpop.h"
|
||||
|
@ -40,6 +40,7 @@
|
|||
#include "libc/sock/sock.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
#define OPEN_MAX 16
|
||||
|
@ -156,12 +157,29 @@ textstartup void __init_fds(int argc, char **argv, char **envp) {
|
|||
f->kind = kind;
|
||||
f->flags = flags;
|
||||
f->mode = mode;
|
||||
f->pointer = pointer;
|
||||
f->type = type;
|
||||
f->family = family;
|
||||
f->protocol = protocol;
|
||||
atomic_store_explicit(&fds->f, fd + 1, memory_order_relaxed);
|
||||
|
||||
//
|
||||
// - v1 abi: This field was originally the file pointer.
|
||||
//
|
||||
// - v2 abi: This field is the negated shared memory address.
|
||||
//
|
||||
if (f->kind == kFdFile) {
|
||||
if (pointer < 0) {
|
||||
f->shared = (struct Cursor *)(uintptr_t)-pointer;
|
||||
} else if ((f->shared = __cursor_new())) {
|
||||
f->shared->pointer = pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
struct Fd *f = fds->p + i;
|
||||
if (f->kind == kFdFile && !f->shared)
|
||||
f->shared = __cursor_new();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_FD_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_FD_INTERNAL_H_
|
||||
#include "libc/atomic.h"
|
||||
#include "libc/thread/thread.h"
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define kFdEmpty 0
|
||||
|
@ -13,19 +15,25 @@ COSMOPOLITAN_C_START_
|
|||
#define kFdDevNull 9
|
||||
#define kFdDevRandom 10
|
||||
|
||||
struct Cursor {
|
||||
pthread_mutex_t lock;
|
||||
long pointer;
|
||||
};
|
||||
|
||||
struct Fd {
|
||||
char kind;
|
||||
bool isdup;
|
||||
bool isbound;
|
||||
unsigned flags;
|
||||
unsigned mode;
|
||||
long handle;
|
||||
long pointer;
|
||||
int family;
|
||||
int type;
|
||||
int protocol;
|
||||
unsigned rcvtimeo; /* millis; 0 means wait forever */
|
||||
unsigned sndtimeo; /* millis; 0 means wait forever */
|
||||
void *connect_op;
|
||||
struct Cursor *shared;
|
||||
};
|
||||
|
||||
struct Fds {
|
||||
|
@ -34,5 +42,9 @@ struct Fds {
|
|||
struct Fd *p, *e;
|
||||
};
|
||||
|
||||
void __fd_lock(struct Fd *);
|
||||
void __fd_unlock(struct Fd *);
|
||||
struct Cursor *__cursor_new(void);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_FD_INTERNAL_H_ */
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/intrin/fds.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
void __fds_lock(void) {
|
||||
|
@ -26,3 +28,23 @@ void __fds_lock(void) {
|
|||
void __fds_unlock(void) {
|
||||
pthread_mutex_unlock(&__fds_lock_obj);
|
||||
}
|
||||
|
||||
void __fd_lock(struct Fd *f) {
|
||||
pthread_mutex_lock(&f->shared->lock);
|
||||
}
|
||||
|
||||
void __fd_unlock(struct Fd *f) {
|
||||
pthread_mutex_unlock(&f->shared->lock);
|
||||
}
|
||||
|
||||
struct Cursor *__cursor_new(void) {
|
||||
struct Cursor *c;
|
||||
if ((c = _mapshared(sizeof(struct Cursor)))) {
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
|
||||
pthread_mutex_init(&c->lock, &attr);
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
|
41
libc/intrin/mapshared.c
Normal file
41
libc/intrin/mapshared.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
||||
/**
|
||||
* Creates anonymous shared memory mapping.
|
||||
*
|
||||
* @return memory map address on success, or null w/ errno
|
||||
*/
|
||||
void *_mapshared(size_t size) {
|
||||
void *m;
|
||||
m = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
|
||||
if (m != MAP_FAILED) {
|
||||
return m;
|
||||
}
|
||||
if (errno == ENOMEM && _weaken(__oom_hook)) {
|
||||
_weaken(__oom_hook)(size);
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue