#ifndef SNC_H #define SNC_H /* ========================== * * Mutex * ========================== */ struct snc_lock { struct snc_mutex *mutex; b32 exclusive; }; struct alignas(64) snc_mutex { /* Bit 31 = Exclusive lock is held * Bit 30 = Exclusive lock is pending * Bit 0-30 = Shared locks count */ struct atomic32 v; #if RTC struct atomic32 exclusive_fiber_id; u8 _pad[56]; #else u8 _pad[60]; #endif }; STATIC_ASSERT(sizeof(struct snc_mutex) == 64); /* Padding validation */ STATIC_ASSERT(alignof(struct snc_mutex) == 64); /* Prevent false sharing */ struct snc_lock snc_lock_spin_e(struct snc_mutex *m, i32 spin); struct snc_lock snc_lock_spin_s(struct snc_mutex *m, i32 spin); struct snc_lock snc_lock_e(struct snc_mutex *m); struct snc_lock snc_lock_s(struct snc_mutex *m); void snc_unlock(struct snc_lock *lock); #if RTC # define snc_assert_locked_e(l, m) ASSERT((l)->mutex == (m) && (l)->exclusive == 1) # define snc_assert_locked_e_or_s(l, m) ASSERT((l)->mutex == (m)) #else # define snc_assert_locked_e(l, m) (UNUSED)l # define snc_assert_locked_e_or_s(l, m) (UNUSED)l #endif /* ========================== * * Condition variable * ========================== */ struct alignas(64) snc_cv { struct atomic64 wake_gen; u8 _pad[56]; }; STATIC_ASSERT(sizeof(struct snc_cv) == 64); /* Padding validation */ STATIC_ASSERT(alignof(struct snc_cv) == 64); /* Prevent false sharing */ void snc_cv_wait(struct snc_cv *cv, struct snc_lock *lock); void snc_cv_wait_time(struct snc_cv *cv, struct snc_lock *l, i64 timeout_ns); void snc_cv_signal(struct snc_cv *cv, i32 count); /* ========================== * * Counter * ========================== */ struct alignas(64) snc_counter { struct atomic64 v; u8 _pad[56]; }; STATIC_ASSERT(sizeof(struct snc_counter) == 64); /* Padding validation */ STATIC_ASSERT(alignof(struct snc_counter) == 64); /* Prevent false sharing */ void snc_counter_add(struct snc_counter *counter, i64 x); void snc_counter_wait(struct snc_counter *counter); #endif