1
1
#include "../tock.h"
2
2
3
+ #define STREAMING_PROCESS_SLICE_HEADER_LEN 8
4
+
3
5
typedef struct {
4
- uint8_t * app_buffer_ptr ;
5
- size_t app_buffer_size ;
6
6
uint32_t driver ;
7
7
uint32_t allow ;
8
+ uint8_t * app_buffer_ptr ;
9
+ size_t app_buffer_size ;
10
+ bool app_buffer_is_b ;
8
11
} streaming_process_slice_state_t ;
9
12
10
13
// Initialize a "streaming process slice" read-write allow slot
11
14
//
12
- // This method allows a userspace buffer into a "streaming process
13
- // slice" allow slot, implementing its atomic-swap semantics and
14
- // header layout. The streaming process slice abstraction allows a
15
- // userspace process to lossessly receive data from a kernel
16
- // capsule. This is done by maintaining two buffers, where at any time
17
- // one of which is owned by the kernel (for writing new, incoming data
18
- // into) and one by the application, to process received data. These
19
- // buffers are atomically swapped by the application, upon receipt of
20
- // a signal that some data has been inserted into the kernel-owned
21
- // buffer (such as an upcall).
15
+ // This method allows a userspace buffer into a "streaming process slice" allow
16
+ // slot, implementing its atomic-swap semantics and header layout. The streaming
17
+ // process slice abstraction allows a userspace process to lossessly receive
18
+ // data from a kernel capsule. This is done by maintaining two buffers, where at
19
+ // any time one of which is owned by the kernel (for writing new, incoming data
20
+ // into) and one by the application, to process received data. These buffers are
21
+ // atomically swapped by the application, upon receipt of a signal that some
22
+ // data has been inserted into the kernel-owned buffer (such as an upcall).
23
+ //
24
+ // This method abstracts this interface by consuming two buffers, owned by the
25
+ // application and kernel respectively. It tracks all necessary state in the
26
+ // `streaming_process_slice_state_t` object. This struct is initialized by this
27
+ // method.
22
28
//
23
- // This method abstracts this interface by consuming one buffer and
24
- // splitting it into two halves, owned by the application and kernel
25
- // respectively. It tracks all necessary state in the
26
- // `streaming_process_slice_state_t` object. For this to work, the
27
- // passed buffer must be able to hold at least two streaming process
28
- // slice headers (8 byte each), i.e., it must be at least 16 bytes
29
- // long.
29
+ // The passed buffers must be each be able to hold at least the streaming
30
+ // process slice headers (`STREAMING_PROCESS_SLICE_HEADER_LEN` bytes), in
31
+ // addition to any payload.
30
32
//
31
- // In case of an error while allowing the kernel-owned buffer to the
32
- // specified driver and read-write allow slot, this function converts
33
- // this error-status into a returncode using
34
- // `tock_status_to_returncode` and returns it to the caller. When this
35
- // method returns `RETURNCODE_SUCCESS`, the passed buffer is assumed
36
- // to be owned by this `streaming_process_slice_state_t` and must not
37
- // be used until after a successful call to
38
- // `streaming_process_slice_deinit`. When the buffer is of
39
- // insufficient size, it returns `RETURNCODE_ESIZE`.
33
+ // In case of an error while allowing the kernel-owned buffer to the specified
34
+ // driver and read-write allow slot, this function converts this error-status
35
+ // into a returncode using `tock_status_to_returncode` and returns it to the
36
+ // caller. When this method returns `RETURNCODE_SUCCESS`, the passed buffers are
37
+ // assumed to be owned by this `streaming_process_slice_state_t` and must not be
38
+ // used until after a successful call to `streaming_process_slice_deinit`. When
39
+ // either buffer is of insufficient size, it returns `RETURNCODE_ESIZE` and does
40
+ // not perform any allow operation or initialize the state reference.
40
41
returncode_t streaming_process_slice_init (
41
42
streaming_process_slice_state_t * state ,
42
43
uint32_t driver ,
43
44
uint32_t allow ,
44
- void * buffer ,
45
- size_t size );
45
+ void * buffer_a ,
46
+ size_t size_a ,
47
+ void * buffer_b ,
48
+ size_t size_b );
46
49
47
50
// Swap kernel- for app-owned buffer and get received payload
48
51
//
49
- // This method atomically swaps the kernel-owned and application-owned
50
- // halves of the streaming process slice. This function will reset the
52
+ // This method atomically swaps the kernel-owned and application-owned buffers
53
+ // backing this streaming process slice. This function will reset the
51
54
// application-owned buffers header, applying any flags set in the
52
- // `streaming_process_slice_state_t` and setting the write offset to
53
- // `0`.
55
+ // `streaming_process_slice_state_t` and setting the write offset to `0`.
54
56
//
55
- // Following the swap operation, when returning `RETURNCODE_SUCCESS`,
56
- // it provides the buffer's payload and any kernel-set flags to the
57
- // caller through the `buffer`, `size`, and `exceeded` arguments
58
- // respectively. Callers must either provide pointers to variables for
59
- // these values, or set them to `NULL` in case they are not interested
60
- // in any given value.
57
+ // Following the swap operation, when returning `RETURNCODE_SUCCESS`, it
58
+ // provides the buffer's payload and any kernel-set flags to the caller through
59
+ // the `buffer`, `size`, and `exceeded` arguments respectively. Callers must
60
+ // either provide pointers to variables for these values, or set them to `NULL`
61
+ // in case they are not interested in any given value.
61
62
//
62
63
// This function forwards any error from the underlying `allow_readwrite`
63
64
// operation in its return value. In case of a return value other than
@@ -71,15 +72,21 @@ returncode_t streaming_process_slice_get_and_swap(
71
72
72
73
// Deinitialize an initialized `streaming_process_slice_state_t`
73
74
//
74
- // This function reconstructs the passed into `streaming_process_slice_init` and
75
- // returns it through the `buffer` and `size` arguments (if not set to `NULL`
76
- // respectively).
75
+ // This function returns the buffers passed into `streaming_process_slice_init`
76
+ // through the `buffer_a`, `size_a`, `buffer_b` and `size_b` arguments (if not
77
+ // set to `NULL` respectively). It ensures that the `buffer_a` and `size_a`
78
+ // arguments passed to `streaming_process_slice_init` match those of `buffer_a`
79
+ // and `size_a` for this function, i.e., it will not swap `buffer_a` for
80
+ // `buffer_b`, regardless of the number of calls to
81
+ // `streaming_process_slice_get_and_swap`.
77
82
//
78
83
// This function forwards any error from the underlying `allow_readwrite`
79
84
// operation in its return value. In case of a return value other than
80
85
// `RETURNCODE_SUCCESS`, any values returned in `buffer`, `size` and `exceeded`
81
86
// must not be considered valid.
82
87
returncode_t streaming_process_slice_deinit (
83
88
streaming_process_slice_state_t * state ,
84
- uint8_t * * buffer ,
85
- size_t * size );
89
+ uint8_t * * buffer_a ,
90
+ size_t * size_a ,
91
+ uint8_t * * buffer_b ,
92
+ size_t * size_b );
0 commit comments