#include <litmus/fdso.h> #include <litmus/sched_plugin.h> #include <litmus/trace.h> #include <litmus/litmus.h> #include <litmus/locking.h> #include <litmus/kexclu_affinity.h> static int create_generic_aff_obs(void** obj_ref, obj_type_t type, void* __user arg); static int open_generic_aff_obs(struct od_table_entry* entry, void* __user arg); static int close_generic_aff_obs(struct od_table_entry* entry); static void destroy_generic_aff_obs(obj_type_t type, void* sem); struct fdso_ops generic_affinity_ops = { .create = create_generic_aff_obs, .open = open_generic_aff_obs, .close = close_generic_aff_obs, .destroy = destroy_generic_aff_obs }; static atomic_t aff_obs_id_gen = ATOMIC_INIT(0); static inline bool is_affinity_observer(struct od_table_entry *entry) { return (entry->class == &generic_affinity_ops); } static inline struct affinity_observer* get_affinity_observer(struct od_table_entry* entry) { BUG_ON(!is_affinity_observer(entry)); return (struct affinity_observer*) entry->obj->obj; } static int create_generic_aff_obs(void** obj_ref, obj_type_t type, void* __user arg) { struct affinity_observer* aff_obs; int err; err = litmus->allocate_aff_obs(&aff_obs, type, arg); if (err == 0) { BUG_ON(!aff_obs->lock); aff_obs->type = type; *obj_ref = aff_obs; } return err; } static int open_generic_aff_obs(struct od_table_entry* entry, void* __user arg) { struct affinity_observer* aff_obs = get_affinity_observer(entry); if (aff_obs->ops->open) return aff_obs->ops->open(aff_obs, arg); else return 0; /* default: any task can open it */ } static int close_generic_aff_obs(struct od_table_entry* entry) { struct affinity_observer* aff_obs = get_affinity_observer(entry); if (aff_obs->ops->close) return aff_obs->ops->close(aff_obs); else return 0; /* default: closing succeeds */ } static void destroy_generic_aff_obs(obj_type_t type, void* obj) { struct affinity_observer* aff_obs = (struct affinity_observer*) obj; aff_obs->ops->deallocate(aff_obs); } struct litmus_lock* get_lock_from_od(int od) { extern struct fdso_ops generic_lock_ops; struct od_table_entry *entry = get_entry_for_od(od); if(entry && entry->class == &generic_lock_ops) { return (struct litmus_lock*) entry->obj->obj; } return NULL; } void affinity_observer_new(struct affinity_observer* aff, struct affinity_observer_ops* ops, struct affinity_observer_args* args) { aff->ops = ops; aff->lock = get_lock_from_od(args->lock_od); aff->ident = atomic_inc_return(&aff_obs_id_gen); }