Preprocessor macro expanding to a command
| Space | User/kernel |
| Context | Sync/async |
| May block | No |
| SPL | Any |
| Dynamic memory | No |
#include <SPAD/AC.H>
CALL_IORQ_CANCELABLE(iorq, handler, chained_iorq); This is a preprocessor macro that expands to machine- and compiler-dependent code to call an IORQ. The functionality is similar to CALL_IORQ except that CALL_IORQ_CANCELABLE links the iorq to already posted chained_iorq — when cancel on chained_iorq is attempted, iorq is also canceled.
An AST for this iorq MUST perform IO_DISABLE_CHAIN_CANCEL on chained_iorq — before it frees or reuses iorq (It is good practice to call IO_DISABLE_CHAIN_CANCEL as the first command in the AST). IO_DISABLE_CHAIN_CANCEL will unlink iorq from chained_iorq, if it were not called there would be dangling pointer to uninitialized memory space.
If chained_iorq has already pending cancel, CALL_IORQ_CANCELABLE won't call handler at all and will instead post iorq's AST with status -EINTR.
fn pointing to AST function declared with DECL_AST. The AST function must call IO_DISABLE_CHAIN_CANCEL on chained_iorq. DECL_IOCALL(FUNCTION, SPL_DEV, IORQ) DECL_AST(READ_CHARS, SPL_DEV, AST)IORQ *r;
SIORQ s;
char string[80];
{
  r = RQ;
  s.v.ptr = (unsigned long)string;
  s.v.len = sizeof string;
  s.v.vspace = KERNEL$VIRTUAL;
  s.h = 0;
  s.progress = 0;
  s.fn = READ_CHARS;
  CALL_IORQ_CANCELABLE(s, KERNEL$READ);
  RETURN;
}
{
  IO_DISABLE_CHAIN_CANCEL(SPL_DEV, r);
  if (RQ->status == -EINTR) {
    r->status = -EINTR;
    RETURN_AST(r);
  }
  ... more code ...
}
We declare an IORQ handler FUNCTION that calls another IORQ to read data from handle 0 (terminal). When the IORQ passed to FUNCTION is canceled, reading of data from the terminal is canceled too and returns -EINTR. Our AST READ_CHARS checks this condition and return -EINTR to the IORQ in this case.
Note that because we use global variables, there may not be more FUNCTION requests posted concurrently.