|
PatchworkOS
c9fea19
A non-POSIX operating system.
|
Signal style inter-process communication. More...
Signal style inter-process communication.
Notes are exposed in the /proc/[pid]/note file and are used for inter-process communication (IPC) similarly to signals in Unix-like operating systems. However, instead of being limited to a predefined set of integer values, notes can send arbitrary strings.
To send or receive notes, each process exposes a set of files in its /proc/[pid] directory.
In the kernel, notes are received and handled in the note_handle_pending() function, which is called from an interrupt context.
From the perspective of user space, a thread will be interrupted the next time a kernel to user boundary is crossed, asuming there is a note pending.
The interruption works by having the kernel save the current interrupt frame of the thread and replacing it with a new frame that calls the note handler function registered using notify(). During the handling of the note, no further notes will be delivered to the thread.
Later, when the note handler function calls noted(), the kernel will restore the saved interrupt frame and continue execution from where it left off as if nothing happened. Alternatively, the note handler can choose to exit the thread. If no handler is registered, the thread is killed.
Certain notes will cause the kernel to take special actions and for the sake of consistency, we define some notes that all user processes are expected to handle in a standardized way.
Any such notes are written as a word optionally followed by additional data. For example, a "terminate" note could be send as is or with a reason string like "terminate due to low memory".
When a thread receives this note, it will immediately transition to the THREAD_DYING state, causing the scheduler to kill and free the thread. User space will never see this note.
The thread attempted to divide by zero.
The thread attempted to execute an illegal instruction.
Indicates an interrupt from the user, typically initiated by pressing Ctrl+C in a terminal.
Indicates that the thread made an invalid memory access, such as dereferencing a null or invalid pointer.
Indicates that the process should perform any necessary cleanup and exit gracefully.
All system notes will always start with a single word consisting of only lowercase letters.
If a program wishes to define its own notes, it is best practice to avoid using such words to prevent conflicts with future system notes. For example, here are some safe to use user-defined notes:
Data Structures | |
| struct | note_t |
| Note structure. More... | |
| struct | note_handler_t |
| Per-process note handler. More... | |
| struct | note_queue_t |
| Per-thread note queue. More... | |
Macros | |
| #define | NOTE_MAX 256 |
| Maximum size of a notes buffer. | |
Enumerations | |
| enum | note_queue_flag_t { NOTE_QUEUE_NONE = 0 , NOTE_QUEUE_RECEIVED_KILL = 1 << 0 , NOTE_QUEUE_HANDLING = 1 << 1 } |
| Note queue flags. More... | |
Functions | |
| void | note_handler_init (note_handler_t *handler) |
| Initialize a note handler. | |
| void | note_queue_init (note_queue_t *queue) |
| Initialize a note queue. | |
| uint64_t | note_amount (note_queue_t *queue) |
| The amount of pending notes in a note queue, including special notes. | |
| uint64_t | note_send (note_queue_t *queue, const char *string) |
| Write a note to a note queue. | |
| bool | note_handle_pending (interrupt_frame_t *frame, cpu_t *self) |
| Handle pending notes for the current thread. | |
| enum note_queue_flag_t |
Note queue flags.
Its vital that a certain special notes get handled, even if we run out of memory. Since these notes have a predefined value and we dont care if they get sent multiple times, we can simplify the system such that when the note queue receives a special note instead of pushing it to the queue we just set the corresponding flag.
| Enumerator | |
|---|---|
| NOTE_QUEUE_NONE | |
| NOTE_QUEUE_RECEIVED_KILL | |
| NOTE_QUEUE_HANDLING | User space is currently handling a note. |
| void note_handler_init | ( | note_handler_t * | handler | ) |
| void note_queue_init | ( | note_queue_t * | queue | ) |
| uint64_t note_amount | ( | note_queue_t * | queue | ) |
| uint64_t note_send | ( | note_queue_t * | queue, |
| const char * | string | ||
| ) |
Write a note to a note queue.
| queue | The destination queue. |
| string | The string to write, should be a null-terminated string. |
0. On failure, ERR and errno is set. Definition at line 45 of file note.c.
| bool note_handle_pending | ( | interrupt_frame_t * | frame, |
| cpu_t * | self | ||
| ) |
Handle pending notes for the current thread.
Should only be called from an interrupt context.
If the frame is not from user space, this function will return immediately.
| frame | The interrupt frame. |
| self | The current CPU. |
true if a note was handled, false otherwise. Definition at line 86 of file note.c.