xref: /DragonOS/kernel/src/ipc/signal_types.rs (revision 64aea4b3494bee7375e1c1ee5739c9fab0db0cb7)
1 #![allow(non_camel_case_types)]
2 // 这是signal暴露给其他模块的公有的接口文件
3 
4 use core::ffi::c_void;
5 use core::fmt::Debug;
6 
7 use alloc::vec::Vec;
8 
9 use crate::arch::fpu::FpState;
10 use crate::include::bindings::bindings::NULL;
11 // todo: 将这里更换为手动编写的ffi绑定
12 use crate::include::bindings::bindings::atomic_t;
13 use crate::include::bindings::bindings::pt_regs;
14 use crate::include::bindings::bindings::spinlock_t;
15 use crate::kerror;
16 use crate::libs::ffi_convert::FFIBind2Rust;
17 use crate::libs::ffi_convert::__convert_mut;
18 use crate::libs::ffi_convert::__convert_ref;
19 use crate::libs::refcount::RefCount;
20 
21 /// 请注意,sigset_t这个bitmap, 第0位表示sig=1的信号。也就是说,SignalNumber-1才是sigset_t中对应的位
22 pub type sigset_t = u64;
23 /// 存储信号处理函数的地址(来自用户态)
24 pub type __signalfn_t = u64;
25 pub type __sighandler_t = __signalfn_t;
26 /// 存储信号处理恢复函数的地址(来自用户态)
27 pub type __sigrestorer_fn_t = u64;
28 pub type __sigrestorer_t = __sigrestorer_fn_t;
29 
30 /// 最大的信号数量(改动这个值的时候请同步到signal.h)
31 pub const MAX_SIG_NUM: i32 = 64;
32 /// sigset所占用的u64的数量(改动这个值的时候请同步到signal.h)
33 pub const _NSIG_U64_CNT: i32 = MAX_SIG_NUM / 64;
34 /// 信号处理的栈的栈指针的最小对齐数量
35 pub const STACK_ALIGN: u64 = 16;
36 
37 /// 由于signal_struct总是和sighand_struct一起使用,并且信号处理的过程中必定会对sighand加锁
38 /// 因此signal_struct不用加锁
39 /// **请将该结构体与`include/DragonOS/signal.h`中的保持同步**
40 #[repr(C)]
41 #[derive(Debug, Copy, Clone)]
42 pub struct signal_struct {
43     pub sig_cnt: atomic_t,
44 }
45 
46 impl Default for signal_struct {
47     fn default() -> Self {
48         Self {
49             sig_cnt: Default::default(),
50         }
51     }
52 }
53 
54 /**
55  * sigaction中的信号处理函数结构体
56  * 分为两种处理函数
57  */
58 #[repr(C)]
59 #[derive(Copy, Clone)]
60 pub union sigaction__union_u {
61     pub _sa_handler: __sighandler_t, // 传统处理函数
62     pub _sa_sigaction: ::core::option::Option<
63         unsafe extern "C" fn(
64             sig: ::core::ffi::c_int,
65             sinfo: *mut siginfo,
66             arg1: *mut ::core::ffi::c_void,
67         ),
68     >,
69 }
70 
71 impl core::fmt::Debug for sigaction__union_u {
72     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
73         f.write_str("sigaction__union_u")
74     }
75 }
76 
77 impl Default for sigaction__union_u {
78     fn default() -> Self {
79         Self {
80             _sa_handler: NULL as u64,
81         }
82     }
83 }
84 
85 // ============ sigaction结构体中的的sa_flags的可选值 begin ===========
86 pub const SA_FLAG_DFL: u64 = 1u64 << 0; // 当前sigaction表示系统默认的动作
87 pub const SA_FLAG_IGN: u64 = 1u64 << 1; // 当前sigaction表示忽略信号的动作
88 pub const SA_FLAG_RESTORER: u64 = 1u64 << 2; // 当前sigaction具有用户指定的restorer
89 pub const SA_FLAG_IMMUTABLE: u64 = 1u64 << 3; // 当前sigaction不可被更改
90 
91 /// 所有的sa_flags的mask。(用于去除那些不存在的sa_flags位)
92 pub const SA_ALL_FLAGS: u64 = SA_FLAG_IGN | SA_FLAG_DFL | SA_FLAG_RESTORER | SA_FLAG_IMMUTABLE;
93 
94 // ============ sigaction结构体中的的sa_flags的可选值 end ===========
95 
96 /// 用户态程序传入的SIG_DFL的值
97 pub const USER_SIG_DFL: u64 = 0;
98 /// 用户态程序传入的SIG_IGN的值
99 pub const USER_SIG_IGN: u64 = 1;
100 
101 /**
102  * @brief 信号处理结构体
103  */
104 #[repr(C)]
105 #[derive(Debug, Copy, Clone)]
106 pub struct sigaction {
107     pub _u: sigaction__union_u,
108     pub sa_flags: u64,
109     pub sa_mask: sigset_t, // 为了可扩展性而设置的sa_mask
110     /// 信号处理函数执行结束后,将会跳转到这个函数内进行执行,然后执行sigreturn系统调用
111     pub sa_restorer: __sigrestorer_t,
112 }
113 
114 impl Default for sigaction {
115     fn default() -> Self {
116         Self {
117             _u: Default::default(),
118             sa_flags: Default::default(),
119             sa_mask: Default::default(),
120             sa_restorer: Default::default(),
121         }
122     }
123 }
124 
125 impl sigaction {
126     /// @brief 判断这个sigaction是否被忽略
127     pub fn ignored(&self, _sig: SignalNumber) -> bool {
128         if (self.sa_flags & SA_FLAG_IGN) != 0 {
129             return true;
130         }
131         // todo: 增加对sa_flags为SA_FLAG_DFL,但是默认处理函数为忽略的情况的判断
132 
133         return false;
134     }
135 }
136 
137 /// @brief 用户态传入的sigaction结构体(符合posix规范)
138 /// 请注意,我们会在sys_sigaction函数里面将其转换成内核使用的sigaction结构体
139 #[repr(C)]
140 #[derive(Debug)]
141 pub struct user_sigaction {
142     pub sa_handler: *mut core::ffi::c_void,
143     pub sa_sigaction: *mut core::ffi::c_void,
144     pub sa_mask: sigset_t,
145     pub sa_flags: u64,
146     pub sa_restorer: *mut core::ffi::c_void,
147 }
148 
149 /**
150  * 信号消息的结构体,作为参数传入sigaction结构体中指向的处理函数
151  */
152 #[repr(C)]
153 #[derive(Copy, Clone)]
154 pub struct siginfo {
155     pub _sinfo: __siginfo_union,
156 }
157 #[repr(C)]
158 #[derive(Copy, Clone)]
159 pub union __siginfo_union {
160     pub data: __siginfo_union_data,
161     pub padding: [u64; 4usize],
162 }
163 
164 #[repr(C)]
165 #[derive(Copy, Clone)]
166 pub struct __siginfo_union_data {
167     pub si_signo: i32,
168     pub si_code: i32,
169     pub si_errno: i32,
170     pub reserved: u32,
171     pub _sifields: __sifields,
172 }
173 
174 /**
175  * siginfo中,根据signal的来源不同,该union中对应了不同的数据./=
176  * 请注意,该union最大占用16字节
177  */
178 #[repr(C)]
179 #[derive(Copy, Clone)]
180 pub union __sifields {
181     pub _kill: __sifields__kill,
182 }
183 
184 /**
185  * 来自kill命令的signal
186  */
187 #[repr(C)]
188 #[derive(Debug, Copy, Clone)]
189 pub struct __sifields__kill {
190     pub _pid: i64, /* 发起kill的进程的pid */
191 }
192 
193 impl siginfo {
194     pub fn new(sig: SignalNumber, _si_errno: i32, _si_code: si_code_val) -> Self {
195         siginfo {
196             _sinfo: __siginfo_union {
197                 data: __siginfo_union_data {
198                     si_signo: sig as i32,
199                     si_code: _si_code as i32,
200                     si_errno: _si_errno,
201                     reserved: 0,
202                     _sifields: super::signal_types::__sifields {
203                         _kill: super::signal_types::__sifields__kill { _pid: 0 },
204                     },
205                 },
206             },
207         }
208     }
209 }
210 
211 impl Debug for siginfo {
212     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
213         unsafe {
214             f.write_fmt(format_args!(
215                 "si_signo:{}, si_code:{}, si_errno:{}, _pid:{}",
216                 self._sinfo.data.si_signo,
217                 self._sinfo.data.si_code,
218                 self._sinfo.data.si_errno,
219                 self._sinfo.data._sifields._kill._pid
220             ))
221         }
222     }
223 }
224 
225 /**
226  * @brief 信号处理结构体,位于pcb之中
227  */
228 #[repr(C)]
229 #[derive(Debug, Copy, Clone)]
230 pub struct sighand_struct {
231     pub siglock: spinlock_t,
232     pub count: RefCount,
233     pub action: [sigaction; MAX_SIG_NUM as usize],
234 }
235 
236 impl Default for sighand_struct {
237     fn default() -> Self {
238         Self {
239             siglock: Default::default(),
240             count: Default::default(),
241             action: [Default::default(); MAX_SIG_NUM as usize],
242         }
243     }
244 }
245 
246 /**
247  * @brief 正在等待的信号的标志位
248  */
249 #[repr(C)]
250 #[derive(Debug, Copy, Clone)]
251 pub struct sigpending {
252     pub signal: sigset_t,
253     /// 信号队列
254     pub queue: *mut SigQueue,
255 }
256 
257 /// siginfo中的si_code的可选值
258 /// 请注意,当这个值小于0时,表示siginfo来自用户态,否则来自内核态
259 #[allow(dead_code)]
260 #[repr(i32)]
261 pub enum si_code_val {
262     /// sent by kill, sigsend, raise
263     SI_USER = 0,
264     /// sent by kernel from somewhere
265     SI_KERNEL = 0x80,
266     /// 通过sigqueue发送
267     SI_QUEUE = -1,
268     /// 定时器过期时发送
269     SI_TIMER = -2,
270     /// 当实时消息队列的状态发生改变时发送
271     SI_MESGQ = -3,
272     /// 当异步IO完成时发送
273     SI_ASYNCIO = -4,
274     /// sent by queued SIGIO
275     SI_SIGIO = -5,
276 }
277 
278 impl si_code_val {
279     /// 为si_code_val这个枚举类型实现从i32转换到枚举类型的转换函数
280     #[allow(dead_code)]
281     pub fn from_i32(x: i32) -> si_code_val {
282         match x {
283             0 => Self::SI_USER,
284             0x80 => Self::SI_KERNEL,
285             -1 => Self::SI_QUEUE,
286             -2 => Self::SI_TIMER,
287             -3 => Self::SI_MESGQ,
288             -4 => Self::SI_ASYNCIO,
289             -5 => Self::SI_SIGIO,
290             _ => panic!("si code not valid"),
291         }
292     }
293 }
294 
295 #[allow(dead_code)]
296 #[derive(Debug, Clone, Copy)]
297 #[repr(i32)]
298 pub enum SignalNumber {
299     INVALID = 0,
300     SIGHUP = 1,
301     SIGINT,
302     SIGQUIT,
303     SIGILL,
304     SIGTRAP,
305     /// SIGABRT和SIGIOT共用这个号码
306     SIGABRT_OR_IOT,
307     SIGBUS,
308     SIGFPE,
309     SIGKILL,
310     SIGUSR1,
311 
312     SIGSEGV = 11,
313     SIGUSR2,
314     SIGPIPE,
315     SIGALRM,
316     SIGTERM,
317     SIGSTKFLT,
318     SIGCHLD,
319     SIGCONT,
320     SIGSTOP,
321     SIGTSTP,
322 
323     SIGTTIN = 21,
324     SIGTTOU,
325     SIGURG,
326     SIGXCPU,
327     SIGXFSZ,
328     SIGVTALRM,
329     SIGPROF,
330     SIGWINCH,
331     /// SIGIO和SIGPOLL共用这个号码
332     SIGIO_OR_POLL,
333     SIGPWR,
334 
335     SIGSYS = 31,
336 }
337 
338 /// 为SignalNumber实现判断相等的trait
339 impl PartialEq for SignalNumber {
340     fn eq(&self, other: &SignalNumber) -> bool {
341         *self as i32 == *other as i32
342     }
343 }
344 
345 impl From<i32> for SignalNumber {
346     fn from(value: i32) -> Self {
347         if Self::valid_signal_number(value) {
348             let ret: SignalNumber = unsafe { core::mem::transmute(value) };
349             return ret;
350         } else {
351             kerror!("Try to convert an invalid number to SignalNumber");
352             return SignalNumber::INVALID;
353         }
354     }
355 }
356 impl SignalNumber {
357     /// 判断一个数字是否为可用的信号
358     fn valid_signal_number(x: i32) -> bool {
359         if x > 0 && x < MAX_SIG_NUM {
360             return true;
361         } else {
362             return false;
363         }
364     }
365 }
366 
367 #[allow(dead_code)]
368 pub const SIGRTMIN: i32 = 32;
369 #[allow(dead_code)]
370 pub const SIGRTMAX: i32 = MAX_SIG_NUM;
371 
372 /// @brief 将给定的signal_struct解析为Rust的signal.rs中定义的signal_struct的引用
373 ///
374 /// 这么做的主要原因在于,由于PCB是通过bindgen生成的FFI,因此pcb中的结构体类型都是bindgen自动生成的
375 impl FFIBind2Rust<crate::include::bindings::bindings::signal_struct> for signal_struct {
376     fn convert_mut(
377         src: *mut crate::include::bindings::bindings::signal_struct,
378     ) -> Option<&'static mut Self> {
379         return __convert_mut(src);
380     }
381     fn convert_ref(
382         src: *const crate::include::bindings::bindings::signal_struct,
383     ) -> Option<&'static Self> {
384         return __convert_ref(src);
385     }
386 }
387 
388 /// @brief 将给定的siginfo解析为Rust的signal.rs中定义的siginfo的引用
389 ///
390 /// 这么做的主要原因在于,由于PCB是通过bindgen生成的FFI,因此pcb中的结构体类型都是bindgen自动生成的
391 impl FFIBind2Rust<crate::include::bindings::bindings::siginfo> for siginfo {
392     fn convert_mut(
393         src: *mut crate::include::bindings::bindings::siginfo,
394     ) -> Option<&'static mut Self> {
395         return __convert_mut(src);
396     }
397     fn convert_ref(
398         src: *const crate::include::bindings::bindings::siginfo,
399     ) -> Option<&'static Self> {
400         return __convert_ref(src);
401     }
402 }
403 
404 /// @brief 将给定的sigset_t解析为Rust的signal.rs中定义的sigset_t的引用
405 ///
406 /// 这么做的主要原因在于,由于PCB是通过bindgen生成的FFI,因此pcb中的结构体类型都是bindgen自动生成的
407 impl FFIBind2Rust<crate::include::bindings::bindings::sigset_t> for sigset_t {
408     fn convert_mut(
409         src: *mut crate::include::bindings::bindings::sigset_t,
410     ) -> Option<&'static mut Self> {
411         return __convert_mut(src);
412     }
413     fn convert_ref(
414         src: *const crate::include::bindings::bindings::sigset_t,
415     ) -> Option<&'static Self> {
416         return __convert_ref(src);
417     }
418 }
419 
420 /// @brief 将给定的sigpending解析为Rust的signal.rs中定义的sigpending的引用
421 ///
422 /// 这么做的主要原因在于,由于PCB是通过bindgen生成的FFI,因此pcb中的结构体类型都是bindgen自动生成的
423 impl FFIBind2Rust<crate::include::bindings::bindings::sigpending> for sigpending {
424     fn convert_mut(
425         src: *mut crate::include::bindings::bindings::sigpending,
426     ) -> Option<&'static mut Self> {
427         return __convert_mut(src);
428     }
429     fn convert_ref(
430         src: *const crate::include::bindings::bindings::sigpending,
431     ) -> Option<&'static Self> {
432         return __convert_ref(src);
433     }
434 }
435 
436 /// @brief 将给定的来自bindgen的sighand_struct解析为Rust的signal.rs中定义的sighand_struct的引用
437 ///
438 /// 这么做的主要原因在于,由于PCB是通过bindgen生成的FFI,因此pcb中的结构体类型都是bindgen自动生成的,会导致无法自定义功能的问题。
439 impl FFIBind2Rust<crate::include::bindings::bindings::sighand_struct> for sighand_struct {
440     fn convert_mut(
441         src: *mut crate::include::bindings::bindings::sighand_struct,
442     ) -> Option<&'static mut Self> {
443         return __convert_mut(src);
444     }
445     fn convert_ref(
446         src: *const crate::include::bindings::bindings::sighand_struct,
447     ) -> Option<&'static Self> {
448         return __convert_ref(src);
449     }
450 }
451 
452 /// @brief 将给定的来自bindgen的sigaction解析为Rust的signal.rs中定义的sigaction的引用
453 impl FFIBind2Rust<crate::include::bindings::bindings::sigaction> for sigaction {
454     fn convert_mut(
455         src: *mut crate::include::bindings::bindings::sigaction,
456     ) -> Option<&'static mut Self> {
457         return __convert_mut(src);
458     }
459     fn convert_ref(
460         src: *const crate::include::bindings::bindings::sigaction,
461     ) -> Option<&'static Self> {
462         return __convert_ref(src);
463     }
464 }
465 
466 /// @brief 进程接收到的信号的队列
467 pub struct SigQueue {
468     pub q: Vec<siginfo>,
469 }
470 
471 #[allow(dead_code)]
472 impl SigQueue {
473     /// @brief 初始化一个新的信号队列
474     pub fn new(capacity: usize) -> Self {
475         SigQueue {
476             q: Vec::with_capacity(capacity),
477         }
478     }
479 
480     /// @brief 在信号队列中寻找第一个满足要求的siginfo, 并返回它的引用
481     ///
482     /// @return (第一个满足要求的siginfo的引用; 是否有多个满足条件的siginfo)
483     pub fn find(&self, sig: SignalNumber) -> (Option<&siginfo>, bool) {
484         // 是否存在多个满足条件的siginfo
485         let mut still_pending = false;
486         let mut info: Option<&siginfo> = None;
487 
488         for x in self.q.iter() {
489             if unsafe { x._sinfo.data.si_signo } == sig as i32 {
490                 if info.is_some() {
491                     still_pending = true;
492                     break;
493                 } else {
494                     info = Some(x);
495                 }
496             }
497         }
498         return (info, still_pending);
499     }
500 
501     /// @brief 在信号队列中寻找第一个满足要求的siginfo, 并将其从队列中删除,然后返回这个siginfo
502     ///
503     /// @return (第一个满足要求的siginfo; 从队列中删除前是否有多个满足条件的siginfo)
504     pub fn find_and_delete(&mut self, sig: SignalNumber) -> (Option<siginfo>, bool) {
505         // 是否存在多个满足条件的siginfo
506         let mut still_pending = false;
507         let mut first = true; // 标记变量,记录当前是否已经筛选出了一个元素
508 
509         let filter = |x: &mut siginfo| {
510             if unsafe { x._sinfo.data.si_signo } == sig as i32 {
511                 if !first {
512                     // 如果之前已经筛选出了一个元素,则不把当前元素删除
513                     still_pending = true;
514                     return false;
515                 } else {
516                     // 当前是第一个被筛选出来的元素
517                     first = false;
518                     return true;
519                 }
520             } else {
521                 return false;
522             }
523         };
524         // 从sigqueue中过滤出结果
525         let mut filter_result: Vec<siginfo> = self.q.drain_filter(filter).collect();
526         // 筛选出的结果不能大于1个
527         assert!(filter_result.len() <= 1);
528 
529         return (filter_result.pop(), still_pending);
530     }
531 
532     /// @brief 从sigqueue中删除mask中被置位的信号。也就是说,比如mask的第1位被置为1,那么就从sigqueue中删除所有signum为2的信号的信息。
533     pub fn flush_by_mask(&mut self, mask: &sigset_t) {
534         // 定义过滤器,从sigqueue中删除mask中被置位的信号
535         let filter = |x: &mut siginfo| {
536             if sig_is_member(mask, SignalNumber::from(unsafe { x._sinfo.data.si_signo })) {
537                 true
538             } else {
539                 false
540             }
541         };
542         let filter_result: Vec<siginfo> = self.q.drain_filter(filter).collect();
543         // 回收这些siginfo
544         for x in filter_result {
545             drop(x)
546         }
547     }
548 
549     /// @brief 从C的void*指针转换为static生命周期的可变引用
550     pub fn from_c_void(p: *mut c_void) -> &'static mut SigQueue {
551         let sq = p as *mut SigQueue;
552         let sq = unsafe { sq.as_mut::<'static>() }.unwrap();
553         return sq;
554     }
555 }
556 
557 impl Default for SigQueue {
558     fn default() -> Self {
559         Self {
560             q: Default::default(),
561         }
562     }
563 }
564 
565 /// @brief 清除sigset中,某个信号对应的标志位
566 #[inline]
567 pub fn sigset_del(set: &mut sigset_t, sig: SignalNumber) {
568     let sig = sig as i32 - 1;
569     if _NSIG_U64_CNT == 1 {
570         *set &= !(1 << sig);
571     } else {
572         // 暂时不支持超过64个信号
573         panic!("Unsupported signal number: {:?}", sig);
574     }
575 }
576 
577 /// @brief 将指定的信号在sigset中的对应bit进行置位
578 #[inline]
579 pub fn sigset_add(set: &mut sigset_t, sig: SignalNumber) {
580     *set |= 1 << ((sig as u32) - 1);
581 }
582 
583 /// @brief 将sigset清零
584 #[inline]
585 pub fn sigset_clear(set: &mut sigset_t) {
586     *set = 0;
587 }
588 
589 /// @brief 将mask中置为1的位,在sigset中清零
590 #[inline]
591 pub fn sigset_delmask(set: &mut sigset_t, mask: u64) {
592     *set &= !mask;
593 }
594 
595 /// @brief 判断两个sigset是否相等
596 #[inline]
597 pub fn sigset_equal(a: &sigset_t, b: &sigset_t) -> bool {
598     if _NSIG_U64_CNT == 1 {
599         return *a == *b;
600     }
601     return false;
602 }
603 
604 /// @brief 使用指定的值,初始化sigset(为支持将来超过64个signal留下接口)
605 #[inline]
606 pub fn sigset_init(new_set: &mut sigset_t, mask: u64) {
607     *new_set = mask;
608     match _NSIG_U64_CNT {
609         1 => {}
610         _ => {
611             // 暂时不支持大于64个信号
612             todo!();
613         }
614     };
615 }
616 
617 /// @brief 判断指定的信号在sigset中的对应位是否被置位
618 /// @return true: 给定的信号在sigset中被置位
619 /// @return false: 给定的信号在sigset中没有被置位
620 #[inline]
621 pub fn sig_is_member(set: &sigset_t, _sig: SignalNumber) -> bool {
622     return if 1 & (set >> ((_sig as u32) - 1)) != 0 {
623         true
624     } else {
625         false
626     };
627 }
628 
629 #[repr(C)]
630 #[derive(Debug, Clone, Copy)]
631 pub struct sigframe {
632     /// 指向restorer的地址的指针。(该变量必须放在sigframe的第一位,因为这样才能在handler返回的时候,跳转到对应的代码,执行sigreturn)
633     pub ret_code_ptr: *mut core::ffi::c_void,
634     /// signum
635     pub arg0: u64,
636     /// siginfo pointer
637     pub arg1: usize,
638     /// sigcontext pointer
639     pub arg2: usize,
640 
641     pub handler: *mut c_void,
642     pub info: siginfo,
643     pub context: sigcontext,
644 }
645 
646 #[derive(Debug, Clone, Copy)]
647 pub struct sigcontext {
648     /// sigcontext的标志位
649     pub sc_flags: u64,
650     pub sc_stack: signal_stack, // 信号处理程序备用栈信息
651 
652     pub regs: pt_regs, // 暂存的系统调用/中断返回时,原本要弹出的内核栈帧
653     pub trap_num: u64, // 用来保存线程结构体中的trap_num字段
654     pub oldmask: u64,  // 暂存的执行信号处理函数之前的,被设置block的信号
655     pub cr2: u64,      // 用来保存线程结构体中的cr2字段
656     pub err_code: u64, // 用来保存线程结构体中的err_code字段
657     // todo: 支持x87浮点处理器后,在这里增加浮点处理器的状态结构体指针
658     pub reserved_for_x87_state: u64,
659     pub reserved: [u64; 8],
660 }
661 
662 /// @brief 信号处理备用栈的信息
663 #[derive(Debug, Clone, Copy)]
664 pub struct signal_stack {
665     pub sp: *mut c_void,
666     pub flags: u32,
667     pub size: u32,
668     pub fpstate:FpState,
669 }
670