msg-type.scm 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. (define-module (mach msg-type)
  2. #:export (msg-type-name:unstructured
  3. msg-type-name:bit
  4. msg-type-name:boolean
  5. msg-type-name:integer/16
  6. msg-type-name:integer/32
  7. msg-type-name:char
  8. msg-type-name:integer/8
  9. msg-type-name:real
  10. msg-type-name:integer/64
  11. msg-type-name:string
  12. msg-type-name:move-receive
  13. msg-type-name:move-send
  14. msg-type-name:move-send-once
  15. msg-type-name:copy-send
  16. msg-type-name:make-send
  17. msg-type-name:make-send-once
  18. msg-type-port:receive
  19. msg-type-port:send
  20. msg-type-port:send-once
  21. clear-type-name replace-type-name type-name
  22. clear-type-size replace-type-size type-size
  23. clear-type-number replace-type-number type-number
  24. assign-inline-field assign-longform-field
  25. assign-deallocate-field assign-unused-field
  26. msg-type:inline? msg-type:longform?
  27. msg-type:deallocate? msg-type:unused?)
  28. #:use-module (srfi srfi-60)
  29. #:use-module (srfi srfi-26)
  30. #:use-module (mach ffi)
  31. #:use-module ((rnrs base) #:select (assert))
  32. #:use-module ((system foreign) #:select (sizeof)))
  33. ;; This is documented at
  34. ;; <https://www.gnu.org/software/hurd/gnumach-doc/Message-Format.html>.
  35. ;; Different kinds of message field types.
  36. ;;
  37. ;; The message type consists of:
  38. ;; * a type name (ffi:msg-type-name)
  39. ;; * a type size (size of the datum, in bits)
  40. ;; * a type number (number of data elements)
  41. ;; * some bits (inline, longform, deallocate, unused)
  42. (define ffi:msg-type ffi:unsigned-int)
  43. (define %wrap-msg-type identity)
  44. (define %unwrap-msg-type identity)
  45. ;; This specifies the data type. The actual data
  46. ;; type can be disambiguated by looking at the type size,
  47. ;; and/or by prior knowledge of what the data looks like.
  48. (define-ffi-enum (ffi:msg-type-name ffi:unsigned-int)
  49. (%wrap-msg-type %unwrap-msg-type)
  50. (msg-type-name:unstructured 0)
  51. (msg-type-name:bit 0)
  52. (msg-type-name:boolean 0)
  53. (msg-type-name:integer/16 1)
  54. (msg-type-name:integer/32 2)
  55. (msg-type-name:char 8)
  56. (msg-type-name:byte 9)
  57. (msg-type-name:integer/8 9)
  58. ;; really a float, IIUC
  59. (msg-type-name:real 10)
  60. (msg-type-name:integer/64 11)
  61. (msg-type-name:string 12)
  62. ;; Port rights.
  63. ;; They are documented at
  64. ;; <https://www.gnu.org/software/hurd/gnumach-doc/Exchanging-Port-Rights.html#fn-1>.
  65. ;; Note that send-once and receive-once rights always have a user reference
  66. ;; count of one.
  67. ;; Message carries a receive right.
  68. ;;
  69. ;; When sending, the sender supplies the receive right and loses the right.
  70. ;; (XXX shouldn't this be ‘loses a reference to the right’?).
  71. ;;
  72. ;; The receiver will see msg-type-name:receive.
  73. (msg-type-name:move-receive 16)
  74. ;; The message carries a send right.
  75. ;;
  76. ;; When sending, the sender supplies a send right and loses a reference
  77. ;; to the right. Alternatively, the sender can supply a dead name, which
  78. ;; likewise loses a reference and the receiver will get the dead port.
  79. ;;
  80. ;; The receiver will see msg-type-port:send
  81. ;; (an alias for msg-type-name:move-send).
  82. (msg-type-name:move-send 17)
  83. ;; The message carries a send-once right.
  84. ;;
  85. ;; When sending, the sender supplies a send-once right and the sender
  86. ;; loses that right. Alternatively, the sender can supply a dead name
  87. ;; which loses a user reference and the receiver will get the dead port.
  88. ;;
  89. ;; When receiving, the receiver gains the send-once right
  90. ;; under a new name.
  91. ;;
  92. ;; The receiver will see msg-type-port:send-once
  93. ;; (an alias for msg-type-name:move-send-once).
  94. (msg-type-name:move-send-once 18)
  95. ;; Message carries a send-once right.
  96. ;;
  97. ;; When sending, the sender supplies a send right and the sender
  98. ;; won't lose that right. Alternatively, the caller can supply
  99. ;; a dead name and the receiver will get the dead port.
  100. ;;
  101. ;; The receiver will see msg-type-port:send
  102. ;; (an alias for msg-type-name:move-send).
  103. (msg-type-name:copy-send 19)
  104. ;; The message carries a send right.
  105. ;;
  106. ;; When sending, the sender supplies a receive right,
  107. ;; and the message will hold a send right created from
  108. ;; the receive right.
  109. ;;
  110. ;; The receiver will see msg-type-port:send
  111. ;; (an alias for msg-type-name:move-send).
  112. (msg-type-name:make-send 20)
  113. ;; The message carries a send-once right.
  114. ;;
  115. ;; When sending, the sender supplies a receive right,
  116. ;; and the message will hold a send-once right created
  117. ;; from the receive right.
  118. ;;
  119. ;; The receiver will see msg-type-port:send-once
  120. ;; (an alias for msg-type-name:move-send-once).
  121. (msg-type-name:make-send-once 21))
  122. ;; Some aliases for the receiver.
  123. ;; The message carried a send right, and the receiver
  124. ;; now has the right.
  125. ;;
  126. ;; Unless that would cause overflow, if the receiver already
  127. ;; has a send or receive right to the port under some name, the
  128. ;; user reference count is incremented instead of allocating a
  129. ;; new name.
  130. ;;
  131. ;; In practice, that's just an implementation detail for efficiency,
  132. ;; however. (TODO: spoken like someone who is writing this comment
  133. ;; on a Linux box, and never actually wrote a translator ...)
  134. (define msg-type-port:send msg-type-name:move-send)
  135. ;; The message carried a send-once right, and the receiver
  136. ;; now has the right under a fresh name.
  137. (define msg-type-port:send-once msg-type-name:move-send-once)
  138. ;; The message carried a receive right.
  139. ;;
  140. ;; TODO make-send count is set to zero? Other attributes remain?
  141. ;; TODO stuff about reusing names, seems to be different
  142. ;; than in msg-typ-name:send?
  143. (define msg-type-port:receive msg-type-name:move-receive)
  144. (define %wrap-msg-type-name identity)
  145. (define %unwrap-msg-type-name identity)
  146. ;; The common lisp port has procedures for converting
  147. ;; between ffi:msg-type-name and their symbol representation.
  148. ;; These have been removed, as the mapping is ambigious.
  149. ;; Mask of type name field.
  150. (define %msg-type-name-mask #xff)
  151. ;; Maximal value for type name.
  152. ;; Coincidentally, this is the same as
  153. ;; %msg-type-name-mask.
  154. (define %max-msg-type-name #xff)
  155. (define (clear-type-name value)
  156. "Clear the type name field in @var{value} (a message type)
  157. and return the result."
  158. (%wrap-msg-type
  159. (bitwise-and (%unwrap-msg-type value)
  160. (bitwise-not %msg-type-name-mask))))
  161. (define (replace-type-name value name)
  162. "Set the type name field in @var{value} (a message type) @var{name}
  163. (a message type name) and return the result."
  164. (let ((n (%unwrap-msg-type-name name)))
  165. (assert (and (exact-integer? n) (<= 0 n) (<= n %max-msg-type-name))))
  166. (%wrap-msg-type
  167. (bitwise-ior (%unwrap-msg-type (clear-type-name value))
  168. (%unwrap-msg-type-name name))))
  169. (define (type-name value)
  170. "Extract the type name in @var{value} (a @code{msg:type})."
  171. (%wrap-msg-type-name
  172. (bitwise-and (%unwrap-msg-type value) %msg-type-name-mask)))
  173. ;; Mask of the size field.
  174. (define %msg-type-size-mask #xff00)
  175. ;; Maximal value of size field.
  176. (define %max-msg-type-size #xff)
  177. ;; How many bits must a @code{ffi:msg-type} be shifted to the
  178. ;; right to extract the size field?
  179. (define %msg-type-size-shift 8)
  180. (define (clear-type-size value)
  181. "Clear the type size field of @var{value} (a @code{ffi:msg-type})
  182. and return the result."
  183. (%wrap-msg-type (bitwise-and (%unwrap-msg-type value)
  184. %msg-type-size-mask)))
  185. (define (replace-type-size value size)
  186. "Set the type size field of @var{value} (a @code{ffi:msg-type})
  187. to @var{size} (an exact integer). @var{size} must be an integer
  188. in the closed range [0,@code{%max-msg-type-size}]."
  189. (assert (and (exact-integer? size) (<= 0 size)
  190. (<= size %max-msg-type-size)))
  191. (%wrap-msg-type
  192. (bitwise-ior (%unwrap-msg-type (clear-type-size value))
  193. (ash size %msg-type-size-shift))))
  194. (define (type-size value)
  195. "Extract the size field from @var{value}, a @code{ffi:msg-type}."
  196. (ash (bitwise-and %msg-type-size-mask (%unwrap-msg-type value))
  197. (- %msg-type-size-shift)))
  198. ;; Mask for number field.
  199. (define %msg-type-number-mask #xfff0000)
  200. ;; Maximal number.
  201. (define %max-msg-type-number #xfff)
  202. ;; Shift for type number field.
  203. ;; That is, shift the value by this number of positions to the right
  204. ;; to extract the number field.
  205. (define %msg-type-number-shift 16)
  206. (define (clear-type-number value)
  207. "Clear the type number field of @var{value}, a @code{ffi:msg-type},
  208. and return the result."
  209. (%wrap-msg-type
  210. (bitwise-and (%unwrap-msg-type value)
  211. (bitwise-not %msg-type-number-mask))))
  212. (define (replace-type-number value number)
  213. "Set the type number field of @var{value} (a @code{ffi:msg-type})
  214. to @var{number}, and return the result. @var{number} must be an
  215. exact integer in the closed range [0,@code{%max-msg-type-number}]."
  216. (assert (and (exact-integer? number) (<= 0 number)
  217. (<= number %max-msg-type-number)))
  218. (%wrap-msg-type
  219. (bitwise-ior (%unwrap-msg-type (clear-type-number value))
  220. (ash number %msg-type-number-shift))))
  221. (define (type-number value)
  222. "Return the type number of @var{value} (a @code{ffi:msg-type})."
  223. (ash (bitwise-and (%unwrap-msg-type value) %msg-type-number-mask)
  224. (- %msg-type-number-shift)))
  225. ;; When #f, the actual data resides in a ‘out-of-line region’.
  226. ;; In a message, the type descriptor is followed by the address.
  227. (define %msg-field:inline 28)
  228. ;; The type descriptor is actually a ffi:msg-type-long.
  229. (define %msg-field:longform 29)
  230. ;; When #t, deallocate the memory region fom the sender's address
  231. ;; space when the message is sent.
  232. (define %msg-field:deallocate 30)
  233. ;; Should be zero.
  234. (define %msg-field:unused 31)
  235. (define (make-bit-assigner position)
  236. "Make a procedure accepting an exact integer and a boolean,
  237. that sets the bit at @var{position} to the boolean and returns
  238. the result."
  239. (cut copy-bit position <> <>))
  240. (define (make-bit-tester position)
  241. "Make a procedure accepting an exact integer, that tests whether
  242. the bit at position @var{position} is set."
  243. (cut bit-set? position <>))
  244. (define assign-inline-field
  245. (make-bit-assigner %msg-field:inline))
  246. (define assign-longform-field
  247. (make-bit-assigner %msg-field:longform))
  248. (define assign-deallocate-field
  249. (make-bit-assigner %msg-field:deallocate))
  250. (define assign-unused-field
  251. (make-bit-assigner %msg-field:unused))
  252. (define msg-type:inline?
  253. (make-bit-tester %msg-field:inline))
  254. (define msg-type:longform?
  255. (make-bit-tester %msg-field:longform))
  256. (define msg-type:deallocate?
  257. (make-bit-tester %msg-field:deallocate))
  258. (define msg-type:unused?
  259. (make-bit-tester %msg-field:unused))
  260. (define %msg-type-size (sizeof ffi:msg-type))