123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- (define-module (mach msg-type)
- #:export (msg-type-name:unstructured
- msg-type-name:bit
- msg-type-name:boolean
- msg-type-name:integer/16
- msg-type-name:integer/32
- msg-type-name:char
- msg-type-name:integer/8
- msg-type-name:real
- msg-type-name:integer/64
- msg-type-name:string
- msg-type-name:move-receive
- msg-type-name:move-send
- msg-type-name:move-send-once
- msg-type-name:copy-send
- msg-type-name:make-send
- msg-type-name:make-send-once
- msg-type-port:receive
- msg-type-port:send
- msg-type-port:send-once
- clear-type-name replace-type-name type-name
- clear-type-size replace-type-size type-size
- clear-type-number replace-type-number type-number
- assign-inline-field assign-longform-field
- assign-deallocate-field assign-unused-field
- msg-type:inline? msg-type:longform?
- msg-type:deallocate? msg-type:unused?)
- #:use-module (srfi srfi-60)
- #:use-module (srfi srfi-26)
- #:use-module (mach ffi)
- #:use-module ((rnrs base) #:select (assert))
- #:use-module ((system foreign) #:select (sizeof)))
- ;; This is documented at
- ;; <https://www.gnu.org/software/hurd/gnumach-doc/Message-Format.html>.
- ;; Different kinds of message field types.
- ;;
- ;; The message type consists of:
- ;; * a type name (ffi:msg-type-name)
- ;; * a type size (size of the datum, in bits)
- ;; * a type number (number of data elements)
- ;; * some bits (inline, longform, deallocate, unused)
- (define ffi:msg-type ffi:unsigned-int)
- (define %wrap-msg-type identity)
- (define %unwrap-msg-type identity)
- ;; This specifies the data type. The actual data
- ;; type can be disambiguated by looking at the type size,
- ;; and/or by prior knowledge of what the data looks like.
- (define-ffi-enum (ffi:msg-type-name ffi:unsigned-int)
- (%wrap-msg-type %unwrap-msg-type)
- (msg-type-name:unstructured 0)
- (msg-type-name:bit 0)
- (msg-type-name:boolean 0)
- (msg-type-name:integer/16 1)
- (msg-type-name:integer/32 2)
- (msg-type-name:char 8)
- (msg-type-name:byte 9)
- (msg-type-name:integer/8 9)
- ;; really a float, IIUC
- (msg-type-name:real 10)
- (msg-type-name:integer/64 11)
- (msg-type-name:string 12)
- ;; Port rights.
- ;; They are documented at
- ;; <https://www.gnu.org/software/hurd/gnumach-doc/Exchanging-Port-Rights.html#fn-1>.
- ;; Note that send-once and receive-once rights always have a user reference
- ;; count of one.
- ;; Message carries a receive right.
- ;;
- ;; When sending, the sender supplies the receive right and loses the right.
- ;; (XXX shouldn't this be ‘loses a reference to the right’?).
- ;;
- ;; The receiver will see msg-type-name:receive.
- (msg-type-name:move-receive 16)
- ;; The message carries a send right.
- ;;
- ;; When sending, the sender supplies a send right and loses a reference
- ;; to the right. Alternatively, the sender can supply a dead name, which
- ;; likewise loses a reference and the receiver will get the dead port.
- ;;
- ;; The receiver will see msg-type-port:send
- ;; (an alias for msg-type-name:move-send).
- (msg-type-name:move-send 17)
- ;; The message carries a send-once right.
- ;;
- ;; When sending, the sender supplies a send-once right and the sender
- ;; loses that right. Alternatively, the sender can supply a dead name
- ;; which loses a user reference and the receiver will get the dead port.
- ;;
- ;; When receiving, the receiver gains the send-once right
- ;; under a new name.
- ;;
- ;; The receiver will see msg-type-port:send-once
- ;; (an alias for msg-type-name:move-send-once).
- (msg-type-name:move-send-once 18)
- ;; Message carries a send-once right.
- ;;
- ;; When sending, the sender supplies a send right and the sender
- ;; won't lose that right. Alternatively, the caller can supply
- ;; a dead name and the receiver will get the dead port.
- ;;
- ;; The receiver will see msg-type-port:send
- ;; (an alias for msg-type-name:move-send).
- (msg-type-name:copy-send 19)
- ;; The message carries a send right.
- ;;
- ;; When sending, the sender supplies a receive right,
- ;; and the message will hold a send right created from
- ;; the receive right.
- ;;
- ;; The receiver will see msg-type-port:send
- ;; (an alias for msg-type-name:move-send).
- (msg-type-name:make-send 20)
- ;; The message carries a send-once right.
- ;;
- ;; When sending, the sender supplies a receive right,
- ;; and the message will hold a send-once right created
- ;; from the receive right.
- ;;
- ;; The receiver will see msg-type-port:send-once
- ;; (an alias for msg-type-name:move-send-once).
- (msg-type-name:make-send-once 21))
- ;; Some aliases for the receiver.
- ;; The message carried a send right, and the receiver
- ;; now has the right.
- ;;
- ;; Unless that would cause overflow, if the receiver already
- ;; has a send or receive right to the port under some name, the
- ;; user reference count is incremented instead of allocating a
- ;; new name.
- ;;
- ;; In practice, that's just an implementation detail for efficiency,
- ;; however. (TODO: spoken like someone who is writing this comment
- ;; on a Linux box, and never actually wrote a translator ...)
- (define msg-type-port:send msg-type-name:move-send)
- ;; The message carried a send-once right, and the receiver
- ;; now has the right under a fresh name.
- (define msg-type-port:send-once msg-type-name:move-send-once)
- ;; The message carried a receive right.
- ;;
- ;; TODO make-send count is set to zero? Other attributes remain?
- ;; TODO stuff about reusing names, seems to be different
- ;; than in msg-typ-name:send?
- (define msg-type-port:receive msg-type-name:move-receive)
- (define %wrap-msg-type-name identity)
- (define %unwrap-msg-type-name identity)
- ;; The common lisp port has procedures for converting
- ;; between ffi:msg-type-name and their symbol representation.
- ;; These have been removed, as the mapping is ambigious.
- ;; Mask of type name field.
- (define %msg-type-name-mask #xff)
- ;; Maximal value for type name.
- ;; Coincidentally, this is the same as
- ;; %msg-type-name-mask.
- (define %max-msg-type-name #xff)
- (define (clear-type-name value)
- "Clear the type name field in @var{value} (a message type)
- and return the result."
- (%wrap-msg-type
- (bitwise-and (%unwrap-msg-type value)
- (bitwise-not %msg-type-name-mask))))
- (define (replace-type-name value name)
- "Set the type name field in @var{value} (a message type) @var{name}
- (a message type name) and return the result."
- (let ((n (%unwrap-msg-type-name name)))
- (assert (and (exact-integer? n) (<= 0 n) (<= n %max-msg-type-name))))
- (%wrap-msg-type
- (bitwise-ior (%unwrap-msg-type (clear-type-name value))
- (%unwrap-msg-type-name name))))
- (define (type-name value)
- "Extract the type name in @var{value} (a @code{msg:type})."
- (%wrap-msg-type-name
- (bitwise-and (%unwrap-msg-type value) %msg-type-name-mask)))
- ;; Mask of the size field.
- (define %msg-type-size-mask #xff00)
- ;; Maximal value of size field.
- (define %max-msg-type-size #xff)
- ;; How many bits must a @code{ffi:msg-type} be shifted to the
- ;; right to extract the size field?
- (define %msg-type-size-shift 8)
- (define (clear-type-size value)
- "Clear the type size field of @var{value} (a @code{ffi:msg-type})
- and return the result."
- (%wrap-msg-type (bitwise-and (%unwrap-msg-type value)
- %msg-type-size-mask)))
- (define (replace-type-size value size)
- "Set the type size field of @var{value} (a @code{ffi:msg-type})
- to @var{size} (an exact integer). @var{size} must be an integer
- in the closed range [0,@code{%max-msg-type-size}]."
- (assert (and (exact-integer? size) (<= 0 size)
- (<= size %max-msg-type-size)))
- (%wrap-msg-type
- (bitwise-ior (%unwrap-msg-type (clear-type-size value))
- (ash size %msg-type-size-shift))))
- (define (type-size value)
- "Extract the size field from @var{value}, a @code{ffi:msg-type}."
- (ash (bitwise-and %msg-type-size-mask (%unwrap-msg-type value))
- (- %msg-type-size-shift)))
- ;; Mask for number field.
- (define %msg-type-number-mask #xfff0000)
- ;; Maximal number.
- (define %max-msg-type-number #xfff)
- ;; Shift for type number field.
- ;; That is, shift the value by this number of positions to the right
- ;; to extract the number field.
- (define %msg-type-number-shift 16)
- (define (clear-type-number value)
- "Clear the type number field of @var{value}, a @code{ffi:msg-type},
- and return the result."
- (%wrap-msg-type
- (bitwise-and (%unwrap-msg-type value)
- (bitwise-not %msg-type-number-mask))))
- (define (replace-type-number value number)
- "Set the type number field of @var{value} (a @code{ffi:msg-type})
- to @var{number}, and return the result. @var{number} must be an
- exact integer in the closed range [0,@code{%max-msg-type-number}]."
- (assert (and (exact-integer? number) (<= 0 number)
- (<= number %max-msg-type-number)))
- (%wrap-msg-type
- (bitwise-ior (%unwrap-msg-type (clear-type-number value))
- (ash number %msg-type-number-shift))))
- (define (type-number value)
- "Return the type number of @var{value} (a @code{ffi:msg-type})."
- (ash (bitwise-and (%unwrap-msg-type value) %msg-type-number-mask)
- (- %msg-type-number-shift)))
- ;; When #f, the actual data resides in a ‘out-of-line region’.
- ;; In a message, the type descriptor is followed by the address.
- (define %msg-field:inline 28)
- ;; The type descriptor is actually a ffi:msg-type-long.
- (define %msg-field:longform 29)
- ;; When #t, deallocate the memory region fom the sender's address
- ;; space when the message is sent.
- (define %msg-field:deallocate 30)
- ;; Should be zero.
- (define %msg-field:unused 31)
- (define (make-bit-assigner position)
- "Make a procedure accepting an exact integer and a boolean,
- that sets the bit at @var{position} to the boolean and returns
- the result."
- (cut copy-bit position <> <>))
- (define (make-bit-tester position)
- "Make a procedure accepting an exact integer, that tests whether
- the bit at position @var{position} is set."
- (cut bit-set? position <>))
- (define assign-inline-field
- (make-bit-assigner %msg-field:inline))
- (define assign-longform-field
- (make-bit-assigner %msg-field:longform))
- (define assign-deallocate-field
- (make-bit-assigner %msg-field:deallocate))
- (define assign-unused-field
- (make-bit-assigner %msg-field:unused))
- (define msg-type:inline?
- (make-bit-tester %msg-field:inline))
- (define msg-type:longform?
- (make-bit-tester %msg-field:longform))
- (define msg-type:deallocate?
- (make-bit-tester %msg-field:deallocate))
- (define msg-type:unused?
- (make-bit-tester %msg-field:unused))
- (define %msg-type-size (sizeof ffi:msg-type))
|