twizzler_rt_abi/
object.rs

1//! Interface for objects and object handles.
2
3use core::{
4    ffi::c_void,
5    fmt::{LowerHex, UpperHex},
6    mem::MaybeUninit,
7    ptr::{addr_of, addr_of_mut},
8    sync::atomic::{AtomicU32, AtomicU64, Ordering},
9};
10
11use bitflags::bitflags;
12
13use crate::{
14    bindings::{
15        object_cmd, object_create, object_tie, sync_info, twz_rt_object_cmd, LEN_MUL,
16        OBJECT_CMD_DELETE, OBJECT_CMD_SYNC, OBJECT_CMD_UPDATE,
17    },
18    error::{RawTwzError, ResourceError, TwzError},
19    nk, Result,
20};
21
22/// An object ID.
23#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
24#[repr(transparent)]
25pub struct ObjID(twizzler_types::ObjID);
26
27impl ObjID {
28    /// The number of u64 components that make up an object ID, if split.
29    pub const NR_PARTS: usize = 2;
30
31    /// Build a new object ID from raw.
32    pub const fn new(raw: twizzler_types::ObjID) -> Self {
33        Self(raw)
34    }
35
36    /// Get the raw object ID type.
37    pub const fn raw(&self) -> twizzler_types::ObjID {
38        self.0
39    }
40
41    /// Build an object ID from parts, useful for syscalls.
42    pub const fn from_parts(parts: [u64; Self::NR_PARTS]) -> Self {
43        Self::new(((parts[0] as u128) << 64) | (parts[1] as u128))
44    }
45
46    /// Split the object ID into parts, useful for packing into registers for syscalls.
47    pub const fn parts(&self) -> [u64; Self::NR_PARTS] {
48        [(self.0 >> 64) as u64, (self.0 & 0xffffffffffffffff) as u64]
49    }
50}
51
52impl core::convert::AsRef<ObjID> for ObjID {
53    fn as_ref(&self) -> &ObjID {
54        self
55    }
56}
57
58impl From<twizzler_types::ObjID> for ObjID {
59    fn from(id: twizzler_types::ObjID) -> Self {
60        Self::new(id)
61    }
62}
63
64impl LowerHex for ObjID {
65    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
66        write!(f, "{:x}", self.0)
67    }
68}
69
70impl UpperHex for ObjID {
71    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
72        write!(f, "{:X}", self.0)
73    }
74}
75
76impl core::fmt::Display for ObjID {
77    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
78        write!(f, "ObjID({:x})", self.0)
79    }
80}
81
82impl core::fmt::Debug for ObjID {
83    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
84        write!(f, "ObjID({:x})", self.0)
85    }
86}
87
88/// An object handle, granting access to object memory. An object handle can be in two modes:
89///   - Owning -- the normal mode, which acts like an Arc, and asks the runtime to unmap when
90///     refcount hits zero.
91///   - Unsafe -- internal use only, is NOT owning, but still has pointers. This is totally unsafe
92///     to use, and should not be exposed to users. But sometimes, it can be safe, and faster than
93///     cloning.
94/// ... anyway, in general these have reference counting semantics, via Clone and Drop, like Arc.
95#[repr(transparent)]
96pub struct ObjectHandle(pub(crate) crate::bindings::object_handle);
97
98impl core::fmt::Debug for ObjectHandle {
99    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
100        write!(
101            f,
102            "ObjectHandle({:?}, {:p}, {:x}, {:?})",
103            self.id(),
104            self.start(),
105            self.valid_len(),
106            self.map_flags()
107        )
108    }
109}
110
111unsafe impl Send for ObjectHandle {}
112unsafe impl Sync for ObjectHandle {}
113
114bitflags::bitflags! {
115    /// Flags for mapping objects.
116    #[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord, Debug)]
117    pub struct MapFlags : crate::bindings::map_flags {
118        /// Request READ access.
119        const READ = crate::bindings::MAP_FLAG_R;
120        /// Request WRITE access.
121        const WRITE = crate::bindings::MAP_FLAG_W;
122        /// Request EXECUTE access.
123        const EXEC = crate::bindings::MAP_FLAG_X;
124        /// Persist changes on flush.
125        const PERSIST = crate::bindings::MAP_FLAG_PERSIST;
126        /// Use runtime support for read stability.
127        const INDIRECT = crate::bindings::MAP_FLAG_INDIRECT;
128        const NO_NULLPAGE = crate::bindings::MAP_FLAG_NO_NULLPAGE;
129    }
130}
131
132impl MapFlags {
133    pub fn rw() -> Self {
134        Self::READ | Self::WRITE | Self::PERSIST
135    }
136
137    pub fn rw_volatile() -> Self {
138        Self::READ | Self::WRITE
139    }
140
141    pub fn ro() -> Self {
142        Self::READ | Self::INDIRECT
143    }
144
145    pub fn rx() -> Self {
146        Self::READ | Self::EXEC | Self::INDIRECT
147    }
148}
149
150#[repr(u32)]
151pub enum ObjectCmd {
152    Delete = OBJECT_CMD_DELETE,
153    Sync = OBJECT_CMD_SYNC,
154    Update = OBJECT_CMD_UPDATE,
155}
156
157impl TryFrom<object_cmd> for ObjectCmd {
158    type Error = TwzError;
159
160    fn try_from(value: object_cmd) -> core::result::Result<Self, Self::Error> {
161        match value {
162            OBJECT_CMD_DELETE => Ok(ObjectCmd::Delete),
163            OBJECT_CMD_SYNC => Ok(ObjectCmd::Sync),
164            OBJECT_CMD_UPDATE => Ok(ObjectCmd::Update),
165            _ => Err(TwzError::INVALID_ARGUMENT),
166        }
167    }
168}
169
170#[allow(dead_code)]
171impl ObjectHandle {
172    fn refs(&self) -> *const AtomicU64 {
173        self.0.runtime_info.cast()
174    }
175
176    /// Get a pointer to the start of object data.
177    pub fn start(&self) -> *mut u8 {
178        self.0.start.cast()
179    }
180
181    /// Get a pointer to the metadata structure.
182    pub fn meta(&self) -> *mut MetaInfo {
183        self.0.meta.cast()
184    }
185
186    /// Get a slice of metadata extensions
187    pub fn meta_exts(&self) -> &[MetaExt] {
188        unsafe {
189            core::slice::from_raw_parts(
190                self.0.meta.cast::<u8>().add(size_of::<MetaInfo>()).cast(),
191                (*self.meta()).extcount as usize,
192            )
193        }
194    }
195
196    /// Get a slice of metadata extensions
197    fn all_meta_exts(&self) -> &[MetaExt] {
198        unsafe {
199            core::slice::from_raw_parts(
200                self.0.meta.cast::<u8>().add(size_of::<MetaInfo>()).cast(),
201                16,
202            )
203        }
204    }
205
206    /// Find the first metadata extension matching the given tag
207    pub fn find_meta_ext(&self, tag: MetaExtTag) -> Option<&MetaExt> {
208        self.meta_exts()
209            .iter()
210            .find(|e| e.value.load(Ordering::SeqCst) != 0 && e.tag == tag)
211    }
212
213    pub unsafe fn set_meta_ext(&self, ext: MetaExt) -> Result<()> {
214        let meta_exts = self.meta_exts();
215        for me in meta_exts {
216            if me.tag == ext.tag {
217                me.value
218                    .store(ext.value.load(Ordering::SeqCst), Ordering::SeqCst);
219                return Ok(());
220            }
221        }
222        let meta_exts = self.all_meta_exts();
223        for (idx, me) in meta_exts.iter().enumerate() {
224            if me.tag == MEXT_EMPTY {
225                if me
226                    .value
227                    .swap(ext.value.load(Ordering::Relaxed), Ordering::SeqCst)
228                    == 0
229                {
230                    let ptr = addr_of!(me.tag) as *mut MetaExtTag;
231                    ptr.write(ext.tag);
232                    (*self.meta()).extcount = (idx + 1) as u16;
233                    return Ok(());
234                }
235            }
236        }
237        Err(TwzError::Resource(ResourceError::OutOfResources))
238    }
239
240    /// Get a pointer to the runtime info.
241    pub fn runtime_info(&self) -> *mut u8 {
242        self.0.runtime_info.cast()
243    }
244
245    /// Get map flags.
246    pub fn map_flags(&self) -> MapFlags {
247        MapFlags::from_bits_truncate(self.0.map_flags)
248    }
249
250    /// Get the number of valid bytes after start pointer for object data.
251    pub fn valid_len(&self) -> usize {
252        (self.0.valid_len as usize) * crate::bindings::LEN_MUL
253    }
254
255    /// Get the object ID.
256    pub fn id(&self) -> ObjID {
257        ObjID::new(self.0.id)
258    }
259
260    /// Get the raw object handle.
261    pub fn into_raw(self) -> crate::bindings::object_handle {
262        let this = core::mem::ManuallyDrop::new(self);
263        this.0
264    }
265
266    /// Build an object handle from raw.
267    pub fn from_raw(raw: crate::bindings::object_handle) -> Self {
268        Self(raw)
269    }
270
271    /// Modify an object.
272    pub fn cmd<T>(&self, cmd: ObjectCmd, arg: *mut T) -> Result<()> {
273        let err = unsafe {
274            nk!(twz_rt_object_cmd(
275                &self.0 as *const _ as *mut _,
276                cmd as object_cmd,
277                arg.cast()
278            ))
279        };
280        let raw = RawTwzError::new(err);
281        if raw.is_success() {
282            Ok(())
283        } else {
284            Err(raw.error())
285        }
286    }
287
288    /// Make a new object handle.
289    ///
290    /// # Safety
291    /// The caller must ensure that runtime_info is a valid pointer, and points to a repr(C) struct
292    /// that starts with an AtomicU64 for reference counting.
293    pub unsafe fn new(
294        id: ObjID,
295        runtime_info: *mut core::ffi::c_void,
296        start: *mut core::ffi::c_void,
297        meta: *mut core::ffi::c_void,
298        map_flags: MapFlags,
299        valid_len: usize,
300    ) -> Self {
301        Self::from_raw(crate::bindings::object_handle {
302            id: id.0,
303            runtime_info,
304            start,
305            meta,
306            map_flags: map_flags.bits(),
307            valid_len: (valid_len / LEN_MUL) as u32,
308        })
309    }
310}
311
312impl Clone for ObjectHandle {
313    fn clone(&self) -> Self {
314        unsafe {
315            let Some(ref rc) = self.refs().as_ref() else {
316                return Self(self.0);
317            };
318            // This use of Relaxed ordering is justified by https://doc.rust-lang.org/nomicon/arc-mutex/arc-clone.html.
319            let old_count = rc.fetch_add(1, Ordering::Relaxed);
320            // The above link also justifies the following behavior. If our count gets this high, we
321            // have probably run into a problem somewhere.
322            if old_count >= i64::MAX as u64 {
323                nk!(crate::core::twz_rt_abort());
324            }
325        }
326        Self(self.0)
327    }
328}
329
330impl Drop for ObjectHandle {
331    fn drop(&mut self) {
332        unsafe {
333            let Some(ref rc) = self.refs().as_ref() else {
334                return;
335            };
336            // This use of Release ordering is justified by https://doc.rust-lang.org/nomicon/arc-mutex/arc-clone.html.
337            if rc.fetch_sub(1, Ordering::Release) != 1 {
338                return;
339            }
340        }
341        // This fence is needed to prevent reordering of the use and deletion
342        // of the data.
343        core::sync::atomic::fence(Ordering::Acquire);
344        nk!(twz_rt_release_handle(self, 0));
345    }
346}
347
348impl AsRef<ObjectHandle> for ObjectHandle {
349    fn as_ref(&self) -> &ObjectHandle {
350        self
351    }
352}
353
354impl From<Result<ObjectHandle>> for crate::bindings::map_result {
355    fn from(value: Result<ObjectHandle>) -> Self {
356        match value {
357            Ok(handle) => Self {
358                handle: handle.into_raw(),
359                error: RawTwzError::success().raw(),
360            },
361            Err(e) => Self {
362                handle: crate::bindings::object_handle::default(),
363                error: e.raw(),
364            },
365        }
366    }
367}
368
369impl From<crate::bindings::map_result> for Result<ObjectHandle> {
370    fn from(value: crate::bindings::map_result) -> Self {
371        let raw = RawTwzError::new(value.error);
372        if raw.is_success() {
373            Ok(ObjectHandle(value.handle))
374        } else {
375            Err(raw.error())
376        }
377    }
378}
379
380/// Map an object given by ID `id` with the given flags.
381pub fn twz_rt_map_object(id: ObjID, flags: MapFlags) -> Result<ObjectHandle> {
382    unsafe { nk!(crate::bindings::twz_rt_map_object(id.raw(), flags.bits()).into()) }
383}
384
385pub fn twz_rt_get_object_handle(ptr: *const u8) -> Result<ObjectHandle> {
386    use crate::error::ObjectError;
387
388    let res = unsafe {
389        nk!(crate::bindings::twz_rt_get_object_handle(
390            (ptr as *mut u8).cast()
391        ))
392    };
393    if res.id == 0 {
394        return Err(TwzError::Object(ObjectError::NotMapped));
395    }
396    Ok(ObjectHandle(res))
397}
398
399pub fn twz_rt_resolve_fot(
400    this: &ObjectHandle,
401    idx: u64,
402    valid_len: usize,
403    flags: MapFlags,
404) -> Result<ObjectHandle> {
405    unsafe {
406        nk!(crate::bindings::twz_rt_resolve_fot(
407            &this.0 as *const _ as *mut _,
408            idx,
409            valid_len,
410            flags.bits(),
411        ))
412        .into()
413    }
414}
415
416impl From<Result<u32>> for crate::bindings::u32_result {
417    fn from(value: Result<u32>) -> Self {
418        match value {
419            Ok(val) => Self {
420                val,
421                err: RawTwzError::success().raw(),
422            },
423            Err(e) => Self {
424                val: 0,
425                err: e.raw(),
426            },
427        }
428    }
429}
430
431impl From<crate::bindings::u32_result> for Result<u32> {
432    fn from(value: crate::bindings::u32_result) -> Self {
433        let raw = RawTwzError::new(value.err);
434        if raw.is_success() {
435            Ok(value.val)
436        } else {
437            Err(raw.error())
438        }
439    }
440}
441
442pub fn twz_rt_insert_fot(this: &ObjectHandle, entry: *const u8) -> Result<u32> {
443    unsafe {
444        let res = nk!(crate::bindings::twz_rt_insert_fot(
445            &this.0 as *const _ as *mut _,
446            (entry as *mut u8).cast(),
447        ));
448        res.into()
449    }
450}
451
452pub fn twz_rt_resolve_fot_local(
453    start: *mut u8,
454    idx: u64,
455    valid_len: usize,
456    flags: MapFlags,
457) -> *mut u8 {
458    unsafe {
459        let res = nk!(crate::bindings::twz_rt_resolve_fot_local(
460            start.cast(),
461            idx,
462            valid_len,
463            flags.bits()
464        ));
465        res.cast()
466    }
467}
468
469use crate::bindings::release_flags;
470
471/// Release a handle. Should be only called by the ObjectHandle drop call.
472pub fn twz_rt_release_handle(handle: &mut ObjectHandle, flags: release_flags) {
473    unsafe { nk!(crate::bindings::twz_rt_release_handle(&mut handle.0, flags)) }
474}
475
476/// Update a handle.
477pub fn twz_rt_update_handle(handle: &mut ObjectHandle) -> Result<()> {
478    let r = unsafe { nk!(crate::bindings::twz_rt_update_handle(&mut handle.0)) };
479    let r = RawTwzError::new(r);
480    if r.is_success() {
481        Ok(())
482    } else {
483        Err(r.error())
484    }
485}
486
487#[deprecated]
488pub fn twz_rt_map_two_objects(
489    id1: ObjID,
490    flags1: MapFlags,
491    id2: ObjID,
492    flags2: MapFlags,
493) -> Result<(ObjectHandle, ObjectHandle)> {
494    unsafe {
495        let mut res1 = MaybeUninit::uninit();
496        let mut res2 = MaybeUninit::uninit();
497        nk!(crate::bindings::__twz_rt_map_two_objects(
498            id1.raw(),
499            flags1.bits(),
500            id2.raw(),
501            flags2.bits(),
502            res1.as_mut_ptr(),
503            res2.as_mut_ptr(),
504        ));
505
506        let res1 = res1.assume_init();
507        let res2 = res2.assume_init();
508
509        let res1: Result<ObjectHandle> = res1.into();
510        let res2: Result<ObjectHandle> = res2.into();
511
512        Ok((res1?, res2?))
513    }
514}
515
516bitflags::bitflags! {
517    /// Mapping protections for mapping objects into the address space.
518    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
519    pub struct Protections: u16 {
520        /// Read allowed.
521        const READ = crate::bindings::MAP_FLAG_R as u16;
522        /// Write allowed.
523        const WRITE = crate::bindings::MAP_FLAG_W as u16;
524        /// Exec allowed.
525        const EXEC = crate::bindings::MAP_FLAG_X as u16;
526    }
527}
528
529impl From<Protections> for MapFlags {
530    fn from(p: Protections) -> Self {
531        let mut f = MapFlags::empty();
532        if p.contains(Protections::READ) {
533            f.insert(MapFlags::READ);
534        }
535
536        if p.contains(Protections::WRITE) {
537            f.insert(MapFlags::WRITE);
538        }
539
540        if p.contains(Protections::EXEC) {
541            f.insert(MapFlags::EXEC);
542        }
543        f
544    }
545}
546
547impl From<MapFlags> for Protections {
548    fn from(value: MapFlags) -> Self {
549        let mut f = Self::empty();
550        if value.contains(MapFlags::READ) {
551            f.insert(Protections::READ);
552        }
553        if value.contains(MapFlags::WRITE) {
554            f.insert(Protections::WRITE);
555        }
556        if value.contains(MapFlags::EXEC) {
557            f.insert(Protections::EXEC);
558        }
559        f
560    }
561}
562
563bitflags::bitflags! {
564/// Flags for objects.
565#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Ord, Eq, Hash, Default)]
566pub struct MetaFlags: u16 {
567    const IMMUTABLE = 1;
568}
569}
570
571/// A nonce for avoiding object ID collision.
572#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Ord, Eq, Hash, Default)]
573#[repr(transparent)]
574pub struct Nonce(pub u128);
575
576/// The core metadata that all objects share.
577#[derive(Clone, Copy, Debug, PartialEq, Hash)]
578#[repr(C)]
579pub struct MetaInfo {
580    /// The ID nonce.
581    pub nonce: Nonce,
582    /// The object's public key ID.
583    pub kuid: ObjID,
584    /// The object flags.
585    pub flags: MetaFlags,
586    /// Default protections
587    pub default_prot: Protections,
588    /// The number of FOT entries.
589    pub fotcount: u16,
590    /// The number of meta extensions.
591    pub extcount: u16,
592}
593
594/// A tag for a meta extension entry.
595#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
596#[repr(transparent)]
597pub struct MetaExtTag(pub u64);
598
599/// A meta extension entry.
600#[repr(C)]
601pub struct MetaExt {
602    /// The tag.
603    pub tag: MetaExtTag,
604    /// A tag-specific value.
605    pub value: AtomicU64,
606}
607
608impl MetaExt {
609    pub fn new(tag: MetaExtTag, value: u64) -> Self {
610        Self {
611            tag,
612            value: AtomicU64::new(value),
613        }
614    }
615}
616
617pub const MEXT_EMPTY: MetaExtTag = MetaExtTag(0);
618pub const MEXT_SIZED: MetaExtTag = MetaExtTag(1);
619
620/// The maximum size of an object, including null page and meta page(s).
621pub const MAX_SIZE: usize = 1024 * 1024 * 1024;
622/// The size of the null page.
623pub const NULLPAGE_SIZE: usize = 0x1000;
624
625#[repr(C)]
626pub struct FotEntry {
627    pub values: [u64; 2],
628    pub resolver: u64,
629    pub flags: AtomicU32,
630}
631
632bitflags::bitflags! {
633    #[repr(C)]
634    #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
635    pub struct FotFlags : u32 {
636        const ALLOCATED = 1;
637        const ACTIVE = 2;
638        const DELETED = 4;
639        const RESOLVER = 8;
640    }
641}
642
643#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Default)]
644#[repr(C)]
645/// Specifications for an object-copy from a source object. The specified ranges are
646/// source:[src_start, src_start + len) copied to `<some unspecified destination
647/// object>:[dest_start, dest_start + len)`. Each range must start within an object, and end within
648/// the object.
649pub struct ObjectSource {
650    /// The ID of the source object, or zero for filling destination with zero.
651    pub id: ObjID,
652    /// The offset into the source object to start the copy. If id is zero, this field is reserved
653    /// for future use.
654    pub src_start: u64,
655    /// The offset into the dest object to start the copy or zero.
656    pub dest_start: u64,
657    /// The length of the copy or zero.
658    pub len: usize,
659}
660
661impl From<ObjectSource> for crate::bindings::object_source {
662    fn from(value: ObjectSource) -> Self {
663        Self {
664            id: value.id.raw(),
665            src_start: value.src_start,
666            dest_start: value.dest_start,
667            len: value.len as u64,
668        }
669    }
670}
671
672impl ObjectSource {
673    /// Construct a new ObjectSource.
674    pub fn new_copy(id: ObjID, src_start: u64, dest_start: u64, len: usize) -> Self {
675        Self {
676            id,
677            src_start,
678            dest_start,
679            len,
680        }
681    }
682
683    /// Construct a new ObjectSource.
684    pub fn new_zero(dest_start: u64, len: usize) -> Self {
685        Self {
686            id: ObjID::new(0),
687            src_start: 0,
688            dest_start,
689            len,
690        }
691    }
692}
693
694#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Default)]
695#[repr(u32)]
696/// The backing memory type for this object. Currently doesn't do anything.
697pub enum BackingType {
698    /// The default, let the kernel decide based on the [LifetimeType] of the object.
699    #[default]
700    Normal = crate::bindings::BACKING_TYPE_NORMAL,
701}
702
703#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Default)]
704#[repr(u32)]
705/// The base lifetime type of the object. Note that this does not ensure that the object is stored
706/// in a specific type of memory, the kernel is allowed to migrate objects with the Normal
707/// [BackingType] as it sees fit. For more information on object lifetime, see [the book](https://twizzler-operating-system.github.io/nightly/book/object_lifetime.html).
708pub enum LifetimeType {
709    /// This object is volatile, and is expected to be deleted after a power cycle.
710    #[default]
711    Volatile = crate::bindings::LIFETIME_TYPE_VOLATILE,
712    /// This object is persistent, and should be deleted only after an explicit delete call.
713    Persistent = crate::bindings::LIFETIME_TYPE_PERSISTENT,
714}
715
716impl From<u32> for LifetimeType {
717    fn from(value: u32) -> Self {
718        match value {
719            crate::bindings::LIFETIME_TYPE_VOLATILE => LifetimeType::Volatile,
720            crate::bindings::LIFETIME_TYPE_PERSISTENT => LifetimeType::Persistent,
721            _ => panic!("Invalid lifetime type"),
722        }
723    }
724}
725
726impl From<u32> for BackingType {
727    fn from(value: u32) -> Self {
728        match value {
729            crate::bindings::BACKING_TYPE_NORMAL => BackingType::Normal,
730            _ => panic!("Invalid backing type"),
731        }
732    }
733}
734
735bitflags! {
736    /// Flags to pass to the object create system call.
737    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
738    pub struct ObjectCreateFlags: u32 {
739        const DELETE = 1;
740        const NO_NONCE = 2;
741    }
742}
743
744bitflags! {
745    /// Flags controlling how a particular object tie operates.
746    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
747    pub struct CreateTieFlags: u32 {
748    }
749}
750
751#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
752#[repr(C)]
753/// Full object creation specification, minus ties.
754pub struct ObjectCreate {
755    pub kuid: ObjID,
756    pub bt: BackingType,
757    pub lt: LifetimeType,
758    pub flags: ObjectCreateFlags,
759    pub def_prot: Protections,
760}
761impl ObjectCreate {
762    /// Build a new object create specification.
763    pub fn new(
764        bt: BackingType,
765        lt: LifetimeType,
766        kuid: Option<ObjID>,
767        flags: ObjectCreateFlags,
768        def_prot: Protections,
769    ) -> Self {
770        Self {
771            kuid: kuid.unwrap_or_else(|| ObjID::new(0)),
772            bt,
773            lt,
774            flags,
775            def_prot,
776        }
777    }
778}
779
780impl Default for ObjectCreate {
781    fn default() -> Self {
782        Self::new(
783            BackingType::Normal,
784            LifetimeType::Volatile,
785            None,
786            ObjectCreateFlags::empty(),
787            Protections::all(),
788        )
789    }
790}
791
792impl From<ObjectCreate> for crate::bindings::object_create {
793    fn from(value: ObjectCreate) -> Self {
794        Self {
795            kuid: value.kuid.0,
796            lifetime: value.lt as u32,
797            backing: value.bt as u32,
798            flags: value.flags.bits(),
799            prot: value.def_prot.bits() as u32,
800        }
801    }
802}
803
804impl From<object_create> for ObjectCreate {
805    fn from(value: object_create) -> Self {
806        Self {
807            kuid: ObjID::new(value.kuid),
808            bt: BackingType::from(value.backing),
809            lt: LifetimeType::from(value.lifetime),
810            flags: ObjectCreateFlags::from_bits_truncate(value.flags),
811            def_prot: Protections::from_bits_truncate(value.prot as u16),
812        }
813    }
814}
815
816#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
817#[repr(C)]
818/// A specification of ties to create.
819/// (see [the book](https://twizzler-operating-system.github.io/nightly/book/object_lifetime.html) for more information on ties).
820pub struct CreateTieSpec {
821    pub id: ObjID,
822    pub flags: CreateTieFlags,
823}
824
825impl CreateTieSpec {
826    /// Create a new CreateTieSpec.
827    pub fn new(id: ObjID, flags: CreateTieFlags) -> Self {
828        Self { id, flags }
829    }
830}
831
832impl From<CreateTieSpec> for object_tie {
833    fn from(value: CreateTieSpec) -> Self {
834        Self {
835            id: value.id.raw(),
836            flags: value.flags.bits(),
837        }
838    }
839}
840
841unsafe impl Send for sync_info {}
842unsafe impl Sync for sync_info {}
843
844impl sync_info {
845    pub unsafe fn try_release(&self) -> Result<()> {
846        self.release_ptr
847            .cast::<AtomicU64>()
848            .as_ref()
849            .unwrap()
850            .compare_exchange(
851                self.release_compare,
852                self.release_set,
853                Ordering::SeqCst,
854                Ordering::SeqCst,
855            )
856            .map_err(|_| TwzError::Resource(ResourceError::Refused))
857            .map(|_| ())
858    }
859
860    pub unsafe fn set_durable(&self, err: impl Into<RawTwzError>) {
861        if self.durable_ptr.is_null() {
862            return;
863        }
864
865        self.durable_ptr
866            .cast::<AtomicU64>()
867            .as_ref()
868            .unwrap()
869            .store(err.into().raw(), Ordering::SeqCst);
870    }
871}