PatchworkOS  c9fea19
A non-POSIX operating system.
Loading...
Searching...
No Matches
Notes

Signal style inter-process communication. More...

Collaboration diagram for Notes:

Detailed Description

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.

Using Notes

To send or receive notes, each process exposes a set of files in its /proc/[pid] directory.

See also
kernel_proc_process

Receiving Notes

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.

System Notes

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".

"kill" (SIGKILL)

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.

"divbyzero" (SIGFPE)

The thread attempted to divide by zero.

"illegal" (SIGILL)

The thread attempted to execute an illegal instruction.

"interrupt" (SIGINT)

Indicates an interrupt from the user, typically initiated by pressing Ctrl+C in a terminal.

"pagefault" (SIGSEGV)

Indicates that the thread made an invalid memory access, such as dereferencing a null or invalid pointer.

"terminate" (SIGTERM)

Indicates that the process should perform any necessary cleanup and exit gracefully.

User-defined Notes

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.
 

Macro Definition Documentation

◆ NOTE_MAX

#define NOTE_MAX   256

Maximum size of a notes buffer.

Definition at line 94 of file note.h.

Enumeration Type Documentation

◆ 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.

Definition at line 104 of file note.h.

Function Documentation

◆ note_handler_init()

void note_handler_init ( note_handler_t handler)

Initialize a note handler.

Parameters
handlerThe handler to initialize.

Definition at line 18 of file note.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ note_queue_init()

void note_queue_init ( note_queue_t queue)

Initialize a note queue.

Parameters
queueThe queue to initialize.

Definition at line 24 of file note.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ note_amount()

uint64_t note_amount ( note_queue_t queue)

The amount of pending notes in a note queue, including special notes.

Parameters
queueThe queue to query.
Returns
The amount of pending notes.

Definition at line 34 of file note.c.

Here is the caller graph for this function:

◆ note_send()

uint64_t note_send ( note_queue_t queue,
const char *  string 
)

Write a note to a note queue.

Parameters
queueThe destination queue.
stringThe string to write, should be a null-terminated string.
Returns
On success, 0. On failure, ERR and errno is set.

Definition at line 45 of file note.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ note_handle_pending()

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.

Parameters
frameThe interrupt frame.
selfThe current CPU.
Returns
true if a note was handled, false otherwise.

Definition at line 86 of file note.c.

Here is the call graph for this function:
Here is the caller graph for this function: