Version: 1.0
Status: Draft
PromptOS provides multiple IPC mechanisms:
| Mechanism | Usage | Speed |
|---|---|---|
| Pipes | Unidirectional data stream | Medium |
| Message Queues | Structured messages | Medium |
| Shared Memory | Large amounts of data | Very fast |
| Futex | Synchronization | Very fast |
| Event Handles | Signaling | Very fast |
handle_t handles[2];
int result = sys_pipe(handles, 0);
// handles[0] = Read end
// handles[1] = Write end#define PIPE_NONBLOCK 0x0001 // Non-blocking I/O
#define PIPE_CLOEXEC 0x0002 // Close on exec// Write
ssize_t written = sys_write(handles[1], data, len);
// Read
char buffer[1024];
ssize_t read = sys_read(handles[0], buffer, sizeof(buffer));- Writing blocks when buffer is full (except PIPE_NONBLOCK)
- Reading blocks when buffer is empty (except PIPE_NONBLOCK)
- Writing to a closed pipe →
EPIPE - Buffer size: 64 KB (configurable)
Message Queues enable structured messages with:
- Priorities (0-31)
- Maximum message size
- Maximum queue depth
// Create/Open
handle_t mq = sys_msgqueue_create("/myqueue", MQ_CREATE | MQ_RDWR);
// Send (Priority 0-31)
struct message {
uint32_t type;
uint32_t length;
char data[256];
};
struct message msg = { .type = 1, .length = 5, .data = "Hello" };
sys_msgqueue_send(mq, &msg, sizeof(msg), 10); // Priority 10
// Receive (highest priority first)
int priority;
ssize_t len = sys_msgqueue_recv(mq, &msg, sizeof(msg), &priority);
// Close
sys_msgqueue_close(mq);#define MQ_CREATE 0x0001 // Create if not exists
#define MQ_EXCL 0x0002 // Error if exists
#define MQ_RDONLY 0x0004 // Read only
#define MQ_WRONLY 0x0008 // Write only
#define MQ_RDWR 0x000C // Read and Write
#define MQ_NONBLOCK 0x0010 // Non-blocking| Limit | Default | Maximum |
|---|---|---|
| Max Message Size | 8 KB | 64 KB |
| Max Queue Depth | 64 | 1024 |
| Max Priority | 31 | 31 |
Shared Memory enables direct memory access between processes. Zero-Copy for maximum performance.
// Create
handle_t shm = sys_shmget(SHM_PRIVATE, 4096, SHM_CREAT | SHM_RDWR);
// Or with name (persistent)
handle_t shm = sys_shmget(SHM_NAME("/myshm"), 4096, SHM_CREAT | SHM_RDWR);
// Map
void *ptr = sys_shmat(shm, NULL, 0);
// Use
memcpy(ptr, data, len);
// Unmap
sys_shmdt(ptr);
// Close handle
sys_close(shm);#define SHM_CREAT 0x0001 // Create
#define SHM_EXCL 0x0002 // Create exclusively
#define SHM_RDONLY 0x0004 // Read only
#define SHM_RDWR 0x0008 // Read and write
// For sys_shmat:
#define SHM_RND 0x0100 // Round down addressShared Memory requires explicit synchronization:
// With Futex
int *lock = (int*)ptr;
// Lock
while (__sync_lock_test_and_set(lock, 1)) {
sys_futex(lock, FUTEX_WAIT, 1, NULL);
}
// Critical section...
// Unlock
*lock = 0;
sys_futex(lock, FUTEX_WAKE, 1, NULL);Futex enables efficient synchronization:
- Fast Path: Purely in userspace (no syscalls)
- Slow Path: Kernel support for blocking/waking
#define FUTEX_WAIT 0 // Wait if *uaddr == val
#define FUTEX_WAKE 1 // Wake up
#define FUTEX_REQUEUE 2 // Wake up and requeue// Wait
// Blocks if *uaddr == val (checked atomically)
int result = sys_futex(&lock, FUTEX_WAIT, expected_value, &timeout);
// Wake up
// Wakes up to 'count' waiting threads
int woken = sys_futex(&lock, FUTEX_WAKE, count, NULL);typedef struct {
int state; // 0 = unlocked, 1 = locked (no waiters), 2 = locked (waiters)
} Mutex;
void mutex_lock(Mutex *m) {
int c;
if ((c = __sync_val_compare_and_swap(&m->state, 0, 1)) != 0) {
// Contention
if (c != 2) {
c = __sync_lock_test_and_set(&m->state, 2);
}
while (c != 0) {
sys_futex(&m->state, FUTEX_WAIT, 2, NULL);
c = __sync_lock_test_and_set(&m->state, 2);
}
}
}
void mutex_unlock(Mutex *m) {
if (__sync_fetch_and_sub(&m->state, 1) != 1) {
m->state = 0;
sys_futex(&m->state, FUTEX_WAKE, 1, NULL);
}
}Event Handles replace traditional Unix signals:
- Explicit polling or blocking
- No race conditions
- Combination with poll()
// Create
handle_t evt = sys_eventfd(0, EFD_SEMAPHORE);
// Signal (increments counter)
uint64_t value = 1;
sys_write(evt, &value, sizeof(value));
// Wait (decrements counter)
uint64_t count;
sys_read(evt, &count, sizeof(count)); // Blocks if counter == 0#define EFD_SEMAPHORE 0x0001 // Semaphore mode (decrement by 1)
#define EFD_NONBLOCK 0x0002 // Non-blocking
#define EFD_CLOEXEC 0x0004 // Close on execstruct pollfd fds[2] = {
{ .fd = socket, .events = POLLIN },
{ .fd = event, .events = POLLIN }
};
int ready = sys_poll(fds, 2, -1);
if (fds[0].revents & POLLIN) {
// Socket has data
}
if (fds[1].revents & POLLIN) {
// Event signaled
}typedef enum {
EVENT_NONE = 0,
EVENT_TERMINATE = 1, // Terminate process (like SIGTERM)
EVENT_INTERRUPT = 2, // Interrupt (like SIGINT)
EVENT_CHILD_EXIT = 3, // Child exited (like SIGCHLD)
EVENT_ALARM = 4, // Timer expired (like SIGALRM)
EVENT_USER1 = 5, // User-defined
EVENT_USER2 = 6, // User-defined
EVENT_WINDOW = 7, // Window size changed
EVENT_IO = 8, // I/O possible
} EventType;// Send event
sys_kill(pid, EVENT_TERMINATE);
// Receive event (via Event Handle)
handle_t proc_events = sys_eventfd(0, 0);
sys_ioctl(proc_events, IOCTL_BIND_PROCESS_EVENTS, EVENT_TERMINATE | EVENT_CHILD_EXIT);
// Wait for events
struct pollfd pfd = { .fd = proc_events, .events = POLLIN };
sys_poll(&pfd, 1, -1);
// Read event
ProcessEvent event;
sys_read(proc_events, &event, sizeof(event));
switch (event.type) {
case EVENT_TERMINATE:
// Cleanup and exit
break;
case EVENT_CHILD_EXIT:
// Handle child process
sys_waitpid(event.pid, &status, WNOHANG);
break;
}Client Server
| |
|-- msgqueue_send(request) --->|
| |-- process request
|<-- msgqueue_send(response) --|
| |
Producer Consumer
| |
|-- write(pipe, data) -------->|
|-- write(pipe, data) -------->|
| |-- read(pipe) + process
| |
Writer Reader
| |
|-- lock(futex) |
|-- write to shm |
|-- unlock(futex) ------------>|-- lock(futex)
| |-- read from shm
| |-- unlock(futex)
- Small messages: Message Queues
- Large amounts of data: Shared Memory + Futex
- Streaming: Pipes
- Signaling: Event Handles
- Low-Latency: Shared Memory with Spinlocks
- Busy-waiting without yield()
- Large messages over Message Queues
- Polling without timeout
- Shared Memory without synchronization
IPC Protocol v1 - PromptOS