| #include <assert.h> |
| #include <string.h> |
| |
| #ifdef IVY_FAST_CHECKS |
| #define SINLINE __attribute__((always_inline)) |
| #else |
| #define SINLINE inline |
| #endif |
| |
| #define SUNUSED __attribute__((unused)) |
| |
| #ifndef sasmlinkage |
| #define sasmlinkage __attribute__((regparm(0))) |
| #endif |
| |
| #ifndef snoreturn |
| #define snoreturn __attribute__((noreturn)) |
| #endif |
| |
| typedef struct __ivy_sharC_thread { |
| #define SHARC_MAX_LOCKS 16 |
| const void *held_locks[SHARC_MAX_LOCKS]; |
| unsigned int max_lock; |
| } sharC_env_t; |
| |
| #include <smp.h> |
| #include <process.h> |
| |
| extern int booting; |
| extern int __ivy_checking_on; |
| |
| #pragma cilnoremove("sharC_env_init") |
| static SINLINE void sharC_env_init(sharC_env_t *sharC_env) TRUSTED; |
| static SINLINE void sharC_env_init(sharC_env_t *sharC_env) |
| WRITES(sharC_env->max_lock,sharC_env->held_locks) |
| { |
| sharC_env->max_lock = 0; |
| memset(sharC_env->held_locks,0,SHARC_MAX_LOCKS); |
| return; |
| } |
| |
| static __attribute__((always_inline)) int |
| is_single_threaded() TRUSTED |
| { |
| return booting || (num_idlecores == num_cpus - 1); |
| } |
| |
| extern void sasmlinkage |
| __sharc_single_thread_error_mayreturn(const char *msg); |
| |
| extern void sasmlinkage snoreturn |
| __sharc_single_thread_error_noreturn(const char *msg); |
| |
| #ifdef IVY_FAST_CHECKS |
| #define __sharc_single_thread_error __sharc_single_thread_error_noreturn |
| #else |
| #define __sharc_single_thread_error __sharc_single_thread_error_mayreturn |
| #endif |
| |
| #pragma cilnoremove("__sharc_single_threaded") |
| static SINLINE void __sharc_single_threaded(const void *msg) TRUSTED; |
| static SINLINE void __sharc_single_threaded(const void *msg) |
| { |
| if (is_single_threaded()) return; |
| __sharc_single_thread_error(msg); |
| return; |
| } |
| |
| #define sharc_current (&per_cpu_info[core_id()]) |
| #define GET_SHARC_THREAD() sharc_current->sharC_env |
| |
| #define THREAD_LOCKS(thread,i) (thread.held_locks[(i)]) |
| #define THREAD_MAX_LOCK(thread) (thread.max_lock) |
| |
| #define THIS_LOCKS(i) (THREAD_LOCKS(GET_SHARC_THREAD(),(i))) |
| #define THIS_MAX_LOCK (THREAD_MAX_LOCK(GET_SHARC_THREAD())) |
| |
| /* |
| * Locks |
| */ |
| |
| extern void sasmlinkage snoreturn |
| __sharc_lock_error_noreturn(const void *lck, const void *what, |
| unsigned int sz, const char *msg); |
| |
| extern void sasmlinkage |
| __sharc_lock_error_mayreturn(const void *lck, const void *what, |
| unsigned int sz, const char *msg); |
| |
| extern void sasmlinkage snoreturn |
| __sharc_lock_coerce_error_noreturn(const void *dstlck, const void *srclck, |
| const char *msg); |
| |
| extern void sasmlinkage |
| __sharc_lock_coerce_error_mayreturn(const void *dstlck, const void *srclck, |
| const char *msg); |
| |
| #ifdef IVY_FAST_CHECKS |
| #define __sharc_lock_error __sharc_lock_error_noreturn |
| #define __sharc_lock_coerce_error __sharc_lock_coerce_error_noreturn |
| #else |
| #define __sharc_lock_error __sharc_lock_error_mayreturn |
| #define __sharc_lock_coerce_error __sharc_lock_coerce_error_mayreturn |
| #endif |
| |
| /* assumes no double-locking */ |
| #pragma cilnoremove("__sharc_add_lock") |
| static SINLINE void __sharc_add_lock(const void *lck) TRUSTED; |
| static SINLINE void __sharc_add_lock(const void *lck) |
| { |
| unsigned int i; |
| |
| if (!__ivy_checking_on || is_single_threaded()) return; |
| |
| for (i = 0; i <= THIS_MAX_LOCK; i++) |
| if (!THIS_LOCKS(i)) |
| break; |
| |
| if (i > THIS_MAX_LOCK && THIS_MAX_LOCK < SHARC_MAX_LOCKS) |
| THIS_MAX_LOCK++; |
| |
| THIS_LOCKS(i) = lck; |
| return; |
| } |
| |
| /* this will be very inefficient if the lock isn't actually held */ |
| #pragma cilnoremove("__sharc_rm_lock") |
| static SINLINE void __sharc_rm_lock(const void *lck) TRUSTED; |
| static SINLINE void __sharc_rm_lock(const void *lck) |
| { |
| unsigned int i; |
| |
| if (!__ivy_checking_on || is_single_threaded()) return; |
| |
| for (i = 0; i <= THIS_MAX_LOCK; i++) |
| if (THIS_LOCKS(i) == lck) |
| break; |
| |
| if (i == THIS_MAX_LOCK && THIS_MAX_LOCK > 0) |
| THIS_MAX_LOCK--; |
| |
| THIS_LOCKS(i) = (void *)0; |
| return; |
| } |
| |
| #pragma cilnoremove("__sharc_chk_lock") |
| static SINLINE void |
| __sharc_chk_lock(const void *lck, const void *what, unsigned int sz, |
| const char *msg) TRUSTED; |
| static SINLINE void |
| __sharc_chk_lock(const void *lck, const void *what, unsigned int sz, |
| const char *msg) |
| { |
| unsigned int i; |
| |
| // TODO: how do I find how many threads are running? |
| //if (__sharc_num_threads == 1) return; |
| |
| if (!__ivy_checking_on || is_single_threaded()) return; |
| |
| for (i = 0; i <= THIS_MAX_LOCK; i++) |
| if (THIS_LOCKS(i) == lck) |
| break; |
| |
| if (i > THIS_MAX_LOCK) { |
| __sharc_lock_error(lck,what,sz,msg); |
| } |
| } |
| |
| #pragma cilnoremove("__sharc_coerce_lock") |
| static SINLINE void |
| __sharc_coerce_lock(const void *dstlck, const void *srclck, |
| const char *msg) TRUSTED; |
| static SINLINE void |
| __sharc_coerce_lock(const void *dstlck, const void *srclck, |
| const char *msg) |
| { |
| if (!__ivy_checking_on || is_single_threaded()) return; |
| |
| if (dstlck != srclck) |
| __sharc_lock_coerce_error(dstlck,srclck,msg); |
| } |
| |
| /* |
| * The sharing cast. |
| * |
| */ |
| |
| extern void __sharc_group_cast_error(int, void *, void *, char *); |
| |
| #pragma cilnoremove("__sharc_check_group_cast") |
| static inline void |
| __sharc_check_group_cast(int hassame, void *srcg, void *src, char *msg) TRUSTED; |
| static inline void |
| __sharc_check_group_cast(int hassame, void *srcg, void *src, char *msg) |
| { |
| int old; |
| if (!__ivy_checking_on) return; |
| old = __ivy_checking_on; |
| __ivy_checking_on = 0; |
| panic("sharc group cast unimplemented"); |
| __ivy_checking_on = old; |
| } |
| |
| |
| extern void __sharc_cast_error(void *addr, unsigned long sz, char *msg); |
| |
| #pragma cilnoremove("__sharc_sharing_cast") |
| static SINLINE void * |
| __sharc_sharing_cast(void *addr,void **slot, unsigned int localslot SUNUSED, |
| unsigned long lo, unsigned long hi, |
| char *msg) TRUSTED; |
| static SINLINE void * |
| __sharc_sharing_cast(void *addr,void **slot, unsigned int localslot SUNUSED, |
| unsigned long lo, unsigned long hi, |
| char *msg) |
| { |
| int old; |
| if (!__ivy_checking_on) return NULL; |
| old = __ivy_checking_on; |
| __ivy_checking_on = 0; |
| panic("sharc sharing cast unimplemented"); |
| __ivy_checking_on = old; |
| return NULL; |
| } |