Function Processing System (FPS)¶
The Function Processing System (FPS) is milk's core framework for managing configuration parameters, states, and commands for compute units. FPS instances provide a high-performance standardized interface directly in shared memory.
See also: Streams · Process Info · Programmer's Guide · FPS Sequencer · pyMilk
1. Architecture and Location¶
An FPS instance creates a shared memory directory structure typically residing under /dev/shm/fps.<fps_name>.datadir/ and /dev/shm/fps.<fps_name>.confdir/. This allows multiple independent processes, CLIs, and GUIs to read and modify a running module's behavior simultaneously without overhead.
2. Key Features¶
-
Parameter Management: FPS maps standard C variables (like strings, integers, and floats) directly into shared memory. When a user updates a parameter via the CLI (e.g.,
milk-fpsCTRLor the module's script), the compute loop instantly sees the change without needing a restart. -
Process State Control: FPS inherently tracks compute unit states such as
run,stop,step, andconf. This allows standard utilities to instruct a running process to pause, take a single execution step, or gracefully shut down. -
CLI & TUI Integration: Standard utilities like
milk-fpsCTRLprovide a Text User Interface (TUI) to interact with FPS instances in real-time. This provides an instant "dashboard" for any correctly built compute module. -
Tmux Dispatch and Isolation: When an FPS process is launched standalone (usually using
milk-fpsexec-<name>,cacao-fps-deploy, or with the-tmuxflag), the command is wrapped and dispatched into its owntmuxsession. This provides complete fault isolation. If one component segmentation faults, it does not bring down the entire pipeline, and its terminal output can be easily examined for debugging.
sequenceDiagram
participant User as CLI User (or Deploy Script)
participant Tmux as Tmux Session
participant FPSData as /dev/shm/fps.* (Shared Config)
participant FPS as Standalone fpsexec process
User->>Tmux: _run_<module> -tmux
Tmux->>FPS: Execute Module Runloop
FPS->>FPSData: Sync State (run/stop/conf)
loop Real-time configuration
User->>FPSData: Change Parameter via fpsCTRL
FPSData-->>FPS: Synchronous Read
FPS->>FPS: Adapt Compute Behavior
end 3. Usage Utilities¶
To use FPS-enabled functions from the command line efficiently, the typical workflow is:
- Define functions and their requested FPS names in
fpslist.txt. - Generate command scripts using
milk-fpsmkcmd. - Launch and manage them via
milk-fpsCTRL.
The fpslist.txt and fpsmkcmd workflow¶
Create a space-delimited text file named fpslist.txt in your working directory. Lines starting with # are comments. Each non-comment line has the format:
Example:
# FPS root name CLI command Optional arguments
fpsrootname0 CLIcommand0
fpsrootname1 CLIcommand1 optarg00 optarg01
Then run milk-fpsmkcmd, which reads fpslist.txt from the current directory and generates per-function scripts in the fpscmd/ subdirectory: <fpsrootname>-fpsinit, <fpsrootname>-confstart, <fpsrootname>-confstop, <fpsrootname>-runstart, <fpsrootname>-runstop. It also writes the resolved FPS names to fpscmd/fpslist.txt, which is the file milk-fpsCTRL reads when scanning with -m _ALL.
milk-fpsCTRL¶
The primary TUI control tool is milk-fpsCTRL. For example, milk-fpsCTRL -m _ALL scans and manages all FPS instances listed in fpscmd/fpslist.txt.
For complete keyboard shortcuts and display modes, see fpsCTRL Reference.
4. Parameter Data Types and Flags¶
FPS natively supports the following parameter types. Use these FPTYPE_* constants in FPS_PARAMS X-macro entries:
| Constant | C Variable Type | Description |
|---|---|---|
FPTYPE_INT32 | int32_t | 32-bit signed integer |
FPTYPE_UINT32 | uint32_t | 32-bit unsigned integer |
FPTYPE_INT64 | int64_t | 64-bit signed integer |
FPTYPE_UINT64 | uint64_t | 64-bit unsigned integer |
FPTYPE_FLOAT32 | float | 32-bit float |
FPTYPE_FLOAT64 | double | 64-bit double |
FPTYPE_ONOFF | int32_t | Boolean (0=OFF, nonzero=ON) |
FPTYPE_STRING | char[FUNCTION_PARAMETER_STRMAXLEN] | Generic text string |
FPTYPE_STREAMNAME | char[FUNCTION_PARAMETER_STRMAXLEN] | SHM stream name |
FPTYPE_FILENAME | char[FUNCTION_PARAMETER_STRMAXLEN] | File path |
FPTYPE_FITSFILENAME | char[FUNCTION_PARAMETER_STRMAXLEN] | FITS file path |
FPTYPE_EXECFILENAME | char[FUNCTION_PARAMETER_STRMAXLEN] | Executable path |
FPTYPE_DIRNAME | char[FUNCTION_PARAMETER_STRMAXLEN] | Directory path |
FPTYPE_FPSNAME | char[FUNCTION_PARAMETER_STRMAXLEN] | Another FPS name |
FPTYPE_PID | pid_t | Process ID |
FPTYPE_TIMESPEC | struct timespec | Timestamp |
FPTYPE_PROCESS | char[FUNCTION_PARAMETER_STRMAXLEN] | Process name |
FPTYPE_STRING_NOT_STREAM | char[FUNCTION_PARAMETER_STRMAXLEN] | String (not a stream) |
For string-type parameters, pass the buffer name directly (it decays to char*). For scalar types, pass &variable.
Flags control parameter behavior and TUI visibility. Combine with bitwise OR (|):
Input/Output presets:
| Flag | Effect |
|---|---|
FPFLAG_DEFAULT_INPUT | Active, used, visible, writable, writeconf, |
| saveonchange, feedback, writestatus | |
FPFLAG_DEFAULT_OUTPUT | Active, used, visible (read-only) |
FPFLAG_DEFAULT_INPUT_STREAM | DEFAULT_INPUT + run-required + stream-check |
FPFLAG_DEFAULT_TRIGGER_STREAM | DEFAULT_INPUT_STREAM + trigger |
FPFLAG_DEFAULT_OUTPUT_STREAM | DEFAULT_INPUT + stream-check (writable, saveable) |
FPFLAG_DEFAULT_STATUS | Active, used, visible (read-only status display) |
Modifiers (combine with presets):
| Flag | Effect |
|---|---|
FPFLAG_MINLIMIT | Enforce minimum value |
FPFLAG_MAXLIMIT | Enforce maximum value |
FPFLAG_WRITERUN | Allow modification while running |
FPFLAG_WRITECONF | Allow modification during config |
FPFLAG_STREAM_ENFORCE_DATATYPE | Validate stream datatype |
Parameters are defined once, in an X-macro table of a MILK_RUNNABLE unit, and generate the FPS entries, the CLI arguments and the help text.
X-macro field order: X(keyword, ptr, type, is_primary, flag, descr)
static char in_name[FUNCTION_PARAMETER_STRMAXLEN];
static double gain = 0.5;
#define MYPARAMS(X) \
X(".in_name", in_name, \
FPTYPE_STREAMNAME, 1, \
FPFLAG_DEFAULT_TRIGGER_STREAM, \
"Input stream") \
X(".gain", &gain, \
FPTYPE_FLOAT64, 0, \
FPFLAG_DEFAULT_INPUT | FPFLAG_WRITERUN,\
"Loop gain")
MILK_PARAMS_DEFINE(my, MYPARAMS);
See the Programmer's Guide and src/milk_module_example/examplefunc_fps_cli_poc.c for a complete unit.
5. Sequencer Integration¶
FPS instances can be highly coordinated via the milk-seq standalone sequencer, which provides cross-process synchronization (wait_fps), robust error handling, loops, and condition-based execution.
See the dedicated FPS Sequencer Documentation for details on the milk-seq daemon, script syntax, and integrating seq.* commands from within milk-cli.
6. Standalone Executables (fpsexec)¶
A compute unit marked with EXPORT_FPSEXEC is built as milk-fpsexec-<id> (or cacao-fpsexec-<id>). It takes native argv, and drives the FPS lifecycle of its shared-memory FPS. Command-line options go before the command, the command goes last.
Options and commands
- Options:
-h,--help: detailed parameter bindings and command help.-h1,--help-oneline: one-line description and exit.-h2,--help-description: verbose description only (no color) and exit.-hm,--help-mono: full help, forced monochrome.-tmux: create atmuxsession and dispatch the commands isolated from the main terminal.-n,--name <fpsname>: override the default FPS shared memory name.-procinfo: enable processinfo entries atfpsinit.-loops: infinite loop with stream semaphore trigger.-loopd <sec>: infinite loop with delay trigger (seconds).
- Commands:
fpsinit: create the FPS shared memory segment.confstart,confstep,confstop: manage the configuration loop.runstart,runstop: manage the execution loop (runis an alias ofrunstart).set [args]: set positional arguments in FPS (use.to skip a position).fps: print the content of the FPS.fpslist: list all FPS instances matching this executable.exec [args]: auto-init, set args and run (one-shot).
Positional arguments that are not a command (e.g. milk-fpsexec-mymod 2.5 100) run the unit once: the executable connects to the FPS if it exists, otherwise creates a local one, maps the arguments onto the primary parameters, and runs the compute function exactly as milk-cli would.