Commit 342bddba authored by Arun Gopalakrishnan's avatar Arun Gopalakrishnan Committed by Hari Kanigeri

Syslink IPC GatePeterson aligned with Syslink drop 2_00_00_06

This patch can be used to sync with the syslink drop 2.0.0.6
for gatepeterson

The major changes are
  1. The atomic function usage came in the above modules
  2. Some logical changes came in some of the functions (create/delete,
     open/close)
Signed-off-by: default avatarArun M G <arunmg@ti.com>
parent 9a945972
......@@ -21,17 +21,24 @@
#include <linux/types.h>
/*
* GATEPETERSON_MODULEID
* Unique module ID
*/
#define GATEPETERSON_MODULEID (0xF415)
/*
* A set of context protection levels that each correspond to
* single processor gates used for local protection
*/
enum gatepeterson_protect {
GATEPETERSON_PROTECT_DEFAULT,
GATEPETERSON_PROTECT_INTERRUPT,
GATEPETERSON_PROTECT_TASKLET,
GATEPETERSON_PROTECT_THREAD,
GATEPETERSON_PROTECT_PROCESS,
GATEPETERSON_PROTECT_NONE
GATEPETERSON_PROTECT_DEFAULT = 0,
GATEPETERSON_PROTECT_NONE = 1,
GATEPETERSON_PROTECT_INTERRUPT = 2,
GATEPETERSON_PROTECT_TASKLET = 3,
GATEPETERSON_PROTECT_THREAD = 4,
GATEPETERSON_PROTECT_PROCESS = 5,
GATEPETERSON_PROTECT_END_VALUE = 6
};
/*
......@@ -39,11 +46,22 @@ enum gatepeterson_protect {
* module
*/
struct gatepeterson_config {
u32 max_name_len; /* GP name len */
enum gatepeterson_protect default_protection;
bool use_nameserver; /* Need a nameserver or not */
u32 max_runtime_entries; /* No of dynamic gps */
void *name_table_gate; /* for nameserver */
/*!< Default module-wide local context protection level. The level of
* protection specified here determines which local gate is created per
* GatePeterson instance for local protection during create. The instance
* configuration parameter may be usedto override this module setting per
* instance. The configuration used here should reflect both the context
* in which enter and leave are to be called,as well as the maximum level
* of protection needed locally.
*/
u32 max_name_len; /* GP name len */
bool use_nameserver;
/*!< Whether to have this module use the NameServer or not. If the
* NameServer is not needed, set this configuration parameter to false.
* This informs GatePeterson not to pull in the NameServer module.
* In this case, all names passed into create and open are ignored.
*/
};
/*
......@@ -52,16 +70,40 @@ struct gatepeterson_config {
*/
struct gatepeterson_params {
void *shared_addr;
/* Address of the shared memory. The creator must supply a cache-aligned
* address in shared memory that will be used to store shared state
* information.
*/
u32 shared_addr_size;
/* Size of the shared memory region. Can use gatepeterson_shared_memreq
* call to determine the required size.
*/
char *name;
u16 opener_proc_id;
/* If using nameserver, name of this instance. The name (if not NULL) must
* be unique among all gatepeterson instances in the entire system.
*/
enum gatepeterson_protect local_protection;
/* Local gate protection level. The default value, (Protect_DEFAULT)
* results in inheritance from module-level defaultProtection. This
* instance setting should be set to an alternative only if a different
* local protection level is needed for the instance.
*/
bool use_nameserver;
/* Whether to have this module use the nameserver or not. If the
* nameserver is not needed, set this configuration parameter to
* false.This informs gatepeterson not to pull in the nameaerver
* module. In this case, all names passed into create and open are
* ignored.
*/
};
/*
* Function to initialize the parameter structure
*/
int gatepeterson_get_config(struct gatepeterson_config *config);
void gatepeterson_get_config(struct gatepeterson_config *config);
/*
* Function to initialize GP module
......@@ -76,7 +118,8 @@ int gatepeterson_destroy(void);
/*
* Function to initialize the parameter structure
*/
int gatepeterson_params_init(struct gatepeterson_params *params);
void gatepeterson_params_init(void *handle,
struct gatepeterson_params *params);
/*
* Function to create an instance of GatePeterson
......@@ -92,7 +135,7 @@ int gatepeterson_delete(void **gphandle);
* Function to open a previously created instance
*/
int gatepeterson_open(void **gphandle,
const struct gatepeterson_params *params);
struct gatepeterson_params *params);
/*
* Function to close a previously opened instance
......
......@@ -123,6 +123,7 @@ enum CMD_GATEPETERSON {
*/
union gatepeterson_arg {
struct {
void *handle;
struct gatepeterson_params *params;
} params_init;
......@@ -138,6 +139,7 @@ union gatepeterson_arg {
void *handle;
struct gatepeterson_params *params;
u32 name_len;
u32 shared_addr_srptr;
} create;
struct {
......@@ -148,6 +150,7 @@ union gatepeterson_arg {
void *handle;
struct gatepeterson_params *params;
u32 name_len;
u32 shared_addr_srptr;
} open;
struct {
......
/*
* gatepeterson.h
* gatepeterson.c
*
* The Gate Peterson Algorithm for mutual exclusion of shared memory.
* Current implementation works for 2 processors.
......@@ -23,15 +23,16 @@
#include <linux/mutex.h>
#include <linux/slab.h>
#include <gt.h>
#include <syslink/atomic_linux.h>
#include <multiproc.h>
#include <nameserver.h>
#include <sharedregion.h>
#include <gatepeterson.h>
/* IPC stubs */
/*
* Name of the reserved NameServer used for GatePeterson
* Name of the reserved NameServer used for gatepeterson
*/
#define GATEPETERSON_NAMESERVER "GatePeterson"
#define GATEPETERSON_BUSY 1
......@@ -41,26 +42,34 @@
was created here */
#define MAX_GATEPETERSON_NAME_LEN 32
/* Cache line size */
#define GATEPETERSON_CACHESIZE 128
/* Macro to make a correct module magic number with ref_count */
#define GATEPETERSON_MAKE_MAGICSTAMP(x) ((GATEPETERSON_MODULEID << 12) | (x))
/*
* structure for GatePeterson module state
* structure for gatepeterson module state
*/
struct gatepeterson_moduleobject {
bool is_init;
atomic_t ref_count; /* Reference count */
void *nshandle;
struct list_head obj_list;
struct mutex *list_lock; /* Lock for obj list */
struct mutex *mod_lock; /* Lock for obj list */
struct gatepeterson_config cfg;
struct gatepeterson_config default_cfg;
struct gatepeterson_params def_inst_params; /* default instance
paramters */
};
/*
* Structure defining attribute parameters for the Gate Peterson module
*/
struct gatepeterson_attrs {
u32 version;
u32 status;
u16 creator_proc_id;
u16 opener_proc_id;
volatile u32 version;
volatile u32 status;
volatile u16 creator_proc_id;
volatile u16 opener_proc_id;
};
/*
......@@ -69,14 +78,16 @@ struct gatepeterson_attrs {
struct gatepeterson_obj {
struct list_head elem;
volatile struct gatepeterson_attrs *attrs; /* Instance attr */
volatile void *flag[2]; /* Falgs for processors */
volatile void *turn; /* Indicates whoes turn it is now? */
u32 nested; /* Counter to track nesting */
volatile u32 *flag[2]; /* Falgs for processors */
volatile u32 *turn; /* Indicates whoes turn it is now? */
u8 self_id; /* Self identifier */
u8 other_id; /* Other's identifier */
u32 nested; /* Counter to track nesting */
void *local_gate; /* Local lock handle */
void *ns_key; /* NameServer key received in create */
enum gatepeterson_protect local_protection; /* Type of local protection
to be used */
struct gatepeterson_params params;
u32 key; /* Value returned by local lock */
void *top; /* Pointer to the top Object */
u32 ref_count; /* Local reference count */
};
......@@ -93,69 +104,88 @@ struct gatepeterson_object {
};
/*
* Variable for holding state of the GatePeterson module
* Variable for holding state of the gatepeterson module
*/
struct gatepeterson_moduleobject gatepeterson_state = {
.obj_list = LIST_HEAD_INIT(gatepeterson_state.obj_list),
.default_cfg.max_name_len = MAX_GATEPETERSON_NAME_LEN,
.default_cfg.default_protection = GATEPETERSON_PROTECT_PROCESS,
.default_cfg.use_nameserver = false,
.default_cfg.max_runtime_entries = ~(0),
.default_cfg.name_table_gate = NULL,
.default_cfg.use_nameserver = true,
.def_inst_params.shared_addr = 0x0,
.def_inst_params.shared_addr_size = 0x0,
.def_inst_params.name = NULL,
.def_inst_params.local_protection = GATEPETERSON_PROTECT_DEFAULT
};
static void *_gatepeterson_create(const struct gatepeterson_params *params,
bool create_flag);
/*
* ======== gatepeterson_get_config ========
* Purpose:
* This will get the default configuration parameters for gatepeterson
* module
*/
int gatepeterson_get_config(struct gatepeterson_config *config)
void gatepeterson_get_config(struct gatepeterson_config *config)
{
s32 retval = 0;
if (WARN_ON(config == NULL)) {
retval = -EINVAL;
if (WARN_ON(config == NULL))
goto exit;
}
if (gatepeterson_state.is_init != true)
if (atomic_cmpmask_and_lt(&(gatepeterson_state.ref_count),
GATEPETERSON_MAKE_MAGICSTAMP(0),
GATEPETERSON_MAKE_MAGICSTAMP(1)) == true)
memcpy(config, &gatepeterson_state.default_cfg,
sizeof(struct gatepeterson_config));
else
memcpy(config, &gatepeterson_state.cfg,
sizeof(struct gatepeterson_config));
return 0;
exit:
return retval;
return;
}
EXPORT_SYMBOL(gatepeterson_get_config);
/*
* ======== gatepeterson_setup ========
* Purpose:
* This will setup the GatePeterson module
* This will setup the gatepeterson module
*/
int gatepeterson_setup(const struct gatepeterson_config *config)
{
struct nameserver_params params;
struct gatepeterson_config tmp_cfg;
void *nshandle = NULL;
s32 retval = 0;
s32 ret;
BUG_ON(config == NULL);
/* This sets the ref_count variable not initialized, upper 16 bits is
* written with module Id to ensure correctness of ref_count variable
*/
atomic_cmpmask_and_set(&gatepeterson_state.ref_count,
GATEPETERSON_MAKE_MAGICSTAMP(0),
GATEPETERSON_MAKE_MAGICSTAMP(0));
if (atomic_inc_return(&gatepeterson_state.ref_count)
!= GATEPETERSON_MAKE_MAGICSTAMP(1)) {
retval = -EEXIST;
goto exit;
}
if (config == NULL) {
gatepeterson_get_config(&tmp_cfg);
config = &tmp_cfg;
}
if (WARN_ON(config->max_name_len == 0)) {
retval = -EINVAL;
goto exit;
}
if (likely((config->use_nameserver == true))) {
retval = nameserver_get_params(NULL, &params);
retval = nameserver_params_init(&params);
params.max_value_len = sizeof(u32);
params.max_name_len = config->max_name_len;
params.gate_handle = config->name_table_gate; /* FIX ME */
params.max_runtime_entries = config->max_runtime_entries;
/* Create the nameserver for modules */
nshandle = nameserver_create(GATEPETERSON_NAMESERVER, &params);
if (nshandle == NULL)
......@@ -166,21 +196,24 @@ int gatepeterson_setup(const struct gatepeterson_config *config)
memcpy(&gatepeterson_state.cfg, config,
sizeof(struct gatepeterson_config));
gatepeterson_state.list_lock = kmalloc(sizeof(struct mutex),
gatepeterson_state.mod_lock = kmalloc(sizeof(struct mutex),
GFP_KERNEL);
if (gatepeterson_state.list_lock == NULL) {
if ((likely(config->use_nameserver == true)))
ret = nameserver_delete(&gatepeterson_state.nshandle);
if (gatepeterson_state.mod_lock == NULL) {
retval = -ENOMEM;
goto exit;
goto lock_create_fail;
}
mutex_init(gatepeterson_state.list_lock);
gatepeterson_state.is_init = true;
mutex_init(gatepeterson_state.mod_lock);
return 0;
lock_create_fail:
if ((likely(config->use_nameserver == true)))
ret = nameserver_delete(&gatepeterson_state.nshandle);
exit:
atomic_set(&gatepeterson_state.ref_count,
GATEPETERSON_MAKE_MAGICSTAMP(0));
printk(KERN_ERR "gatepeterson_setup failed status: %x\n",
retval);
return retval;
......@@ -190,26 +223,48 @@ EXPORT_SYMBOL(gatepeterson_setup);
/*
* ======== gatepeterson_destroy ========
* Purpose:
* This will destroy the GatePeterson module
* This will destroy the gatepeterson module
*/
int gatepeterson_destroy(void)
{
struct gatepeterson_obj *obj = NULL;
struct mutex *lock = NULL;
s32 retval = 0;
if (WARN_ON(gatepeterson_state.is_init != true)) {
if (atomic_cmpmask_and_lt(&(gatepeterson_state.ref_count),
GATEPETERSON_MAKE_MAGICSTAMP(0),
GATEPETERSON_MAKE_MAGICSTAMP(1)) == true) {
retval = -ENODEV;
goto exit;
}
/* If an entry exist, do not proceed */
if (!list_empty(&gatepeterson_state.obj_list)) {
retval = -EBUSY;
goto exit;
if (atomic_dec_return(&gatepeterson_state.ref_count)
== GATEPETERSON_MAKE_MAGICSTAMP(0)) {
/* Temporarily increment ref_count here. */
atomic_set(&gatepeterson_state.ref_count,
GATEPETERSON_MAKE_MAGICSTAMP(1));
/* Check if any gatepeterson instances have not been
* ideleted/closed so far, if there any, delete or close them
*/
list_for_each_entry(obj, &gatepeterson_state.obj_list, elem) {
if (obj->attrs->creator_proc_id ==
multiproc_get_id(NULL))
gatepeterson_delete(&obj->top);
else
gatepeterson_close(&obj->top);
if (list_empty(&gatepeterson_state.obj_list))
break;
}
retval = mutex_lock_interruptible(gatepeterson_state.list_lock);
/* Again reset ref_count. */
atomic_set(&gatepeterson_state.ref_count,
GATEPETERSON_MAKE_MAGICSTAMP(0));
}
retval = mutex_lock_interruptible(gatepeterson_state.mod_lock);
if (retval != 0)
goto exit;
......@@ -219,12 +274,14 @@ int gatepeterson_destroy(void)
goto exit;
}
lock = gatepeterson_state.list_lock;
gatepeterson_state.list_lock = NULL;
lock = gatepeterson_state.mod_lock;
gatepeterson_state.mod_lock = NULL;
memset(&gatepeterson_state.cfg, 0, sizeof(struct gatepeterson_config));
gatepeterson_state.is_init = false;
mutex_unlock(lock);
kfree(lock);
/* Decrease the ref_count */
atomic_set(&gatepeterson_state.ref_count,
GATEPETERSON_MAKE_MAGICSTAMP(0));
return 0;
exit:;
......@@ -240,36 +297,48 @@ EXPORT_SYMBOL(gatepeterson_destroy);
* This will Initialize this config-params structure with
* supplier-specified defaults before instance creation
*/
int gatepeterson_params_init(struct gatepeterson_params *params)
void gatepeterson_params_init(void *handle,
struct gatepeterson_params *params)
{
BUG_ON(params == NULL);
if (WARN_ON(atomic_cmpmask_and_lt(&(gatepeterson_state.ref_count),
GATEPETERSON_MAKE_MAGICSTAMP(0),
GATEPETERSON_MAKE_MAGICSTAMP(1)) == true))
goto exit;
params->shared_addr = 0;
params->shared_addr_size = 0;
params->name = NULL;
params->local_protection = GATEPETERSON_PROTECT_PROCESS;
params->opener_proc_id = MULTIPROC_INVALIDID;
return 0;
if (WARN_ON(params == NULL))
goto exit;
if (handle == NULL)
memcpy(params, &(gatepeterson_state.def_inst_params),
sizeof(struct gatepeterson_params));
else {
struct gatepeterson_obj *obj =
(struct gatepeterson_obj *)handle;
/* Return updated gatepeterson instance specific parameters. */
memcpy(params, &(obj->params),
sizeof(struct gatepeterson_params));
}
exit:
return;
}
EXPORT_SYMBOL(gatepeterson_params_init);
/*
* ======== gatepeterson_create ========
* Purpose:
* This will creates a new instance of GatePeterson module
* This will creates a new instance of gatepeterson module
*/
void *gatepeterson_create(const struct gatepeterson_params *params)
{
struct gatepeterson_object *handle = NULL;
struct gatepeterson_obj *obj = NULL;
void *handle = NULL;
s32 retval = 0;
u32 shaddrsize;
u32 len;
s32 status;
void *entry = NULL;
BUG_ON(params == NULL);
if (WARN_ON(gatepeterson_state.is_init != true)) {
if (atomic_cmpmask_and_lt(&(gatepeterson_state.ref_count),
GATEPETERSON_MAKE_MAGICSTAMP(0),
GATEPETERSON_MAKE_MAGICSTAMP(1)) == true) {
retval = -ENODEV;
goto exit;
}
......@@ -281,112 +350,15 @@ void *gatepeterson_create(const struct gatepeterson_params *params)
goto exit;
}
handle = kmalloc(sizeof(struct gatepeterson_object), GFP_KERNEL);
if (handle == NULL) {
retval = -ENOMEM;
goto handle_alloc_fail;
}
obj = kmalloc(sizeof(struct gatepeterson_obj), GFP_KERNEL);
if (obj == NULL) {
retval = -ENOMEM;
goto obj_alloc_fail;
}
if (likely(gatepeterson_state.cfg.use_nameserver == true &&
params->name != NULL)) {
len = strlen(params->name) + 1;
obj->params.name = kmalloc(len, GFP_KERNEL);
if (obj->params.name == NULL) {
retval = -ENOMEM;
goto name_alloc_fail;
}
strncpy(obj->params.name, params->name, len);
entry = nameserver_add_uint32(gatepeterson_state.nshandle,
params->name,
(u32)(params->shared_addr));
if (entry == NULL)
goto ns_add32_fail;
}
handle->obj = obj;
handle->enter = gatepeterson_enter;
handle->leave = gatepeterson_leave;
handle->lock_get_knl_handle = gatepeterson_get_knl_handle;
/* assign the memory with proper cache line padding */
obj->attrs = (struct gatepeterson_attrs *)params->shared_addr;
obj->flag[0] = ((void *)(((u32)obj->attrs) + 128));
obj->flag[1] = ((void *)(((u32)obj->flag[0]) + 128));
obj->turn = ((void *)(((u32)obj->flag[1]) + 128)); /* TBD: Fixme */
obj->self_id = 0; /* Creator has selfid set to 0 */
obj->other_id = 1;
obj->nested = 0;
obj->ref_count = 0;
obj->attrs->creator_proc_id = multiproc_get_id(NULL);
obj->attrs->opener_proc_id = params->opener_proc_id;
obj->attrs->status = GATEPETERSON_CREATED;
obj->attrs->version = GATEPETERSON_VERSION;
obj->top = handle;
/* Create the local lock if not provided */
if (likely(params->local_protection == GATEPETERSON_PROTECT_DEFAULT))
obj->params.local_protection =
gatepeterson_state.cfg.default_protection;
else
obj->params.local_protection = params->local_protection;
switch (obj->params.local_protection) {
case GATEPETERSON_PROTECT_NONE: /* Fall through */
case GATEPETERSON_PROTECT_INTERRUPT: /* Fall through */
obj->local_gate = NULL; /* TBD: Fixme */
break;
case GATEPETERSON_PROTECT_TASKLET: /* Fall through */
case GATEPETERSON_PROTECT_THREAD: /* Fall through */
case GATEPETERSON_PROTECT_PROCESS:
obj->local_gate = kmalloc(sizeof(struct mutex), GFP_KERNEL);
if (obj->local_gate == NULL) {
retval = -ENOMEM;
goto gate_create_fail;
}
mutex_init(obj->local_gate);
break;
default:
/* An invalid protection level was supplied, FIXME */
break;
if (params->local_protection >= GATEPETERSON_PROTECT_END_VALUE) {
retval = -EINVAL;
goto exit;
}
/* Populate the params member */
memcpy(&obj->params, params, sizeof(struct gatepeterson_params));
/* Put in the local list */
retval = mutex_lock_interruptible(gatepeterson_state.list_lock);
if (retval)
goto list_lock_fail;
list_add_tail(&obj->elem, &gatepeterson_state.obj_list);
mutex_unlock(gatepeterson_state.list_lock);
return (void *)handle;
list_lock_fail:
kfree(obj->local_gate);
gate_create_fail:
status = nameserver_remove(gatepeterson_state.nshandle, params->name);
ns_add32_fail:
kfree(obj->params.name);
handle = _gatepeterson_create(params, true);
return handle;
name_alloc_fail:
kfree(obj);
obj_alloc_fail:
kfree(handle);
handle_alloc_fail: /* Fall through */
exit:
printk(KERN_ERR "gatepeterson_create failed status: %x\n", retval);
return NULL;
}
EXPORT_SYMBOL(gatepeterson_create);
......@@ -394,7 +366,7 @@ EXPORT_SYMBOL(gatepeterson_create);
/*
* ======== gatepeterson_delete ========
* Purpose:
* This will deletes an instance of GatePeterson module
* This will deletes an instance of gatepeterson module
*/
int gatepeterson_delete(void **gphandle)
......@@ -406,13 +378,25 @@ int gatepeterson_delete(void **gphandle)
BUG_ON(gphandle == NULL);
BUG_ON(*gphandle == NULL);
if (WARN_ON(gatepeterson_state.is_init != true)) {
if (atomic_cmpmask_and_lt(&(gatepeterson_state.ref_count),
GATEPETERSON_MAKE_MAGICSTAMP(0),
GATEPETERSON_MAKE_MAGICSTAMP(1)) == true) {
retval = -ENODEV;
goto exit;
}
handle = (struct gatepeterson_object *)(*gphandle);
obj = (struct gatepeterson_obj *)handle->obj;
if (obj == NULL) {
retval = -EINVAL;
goto exit;
}
if (obj->attrs == NULL) {
retval = -EINVAL;
goto exit;
}
/* Check if we have created the GP or not */
if (obj->attrs->creator_proc_id != multiproc_get_id(NULL)) {
retval = -EACCES;
......@@ -424,35 +408,36 @@ int gatepeterson_delete(void **gphandle)
goto exit;
if (obj->ref_count != 0) {
obj->ref_count--;
retval = -EBUSY;
goto error_handle;
}
retval = mutex_lock_interruptible(gatepeterson_state.list_lock);
obj->attrs->status = !GATEPETERSON_CREATED;
retval = mutex_lock_interruptible(gatepeterson_state.mod_lock);
if (retval)
goto error_handle;
goto exit;
list_del(&obj->elem); /* Remove the GP instance from the GP list */
mutex_unlock(gatepeterson_state.list_lock);
mutex_unlock(gatepeterson_state.mod_lock);
params = &obj->params;
/* Remove from the name server */
if (likely(gatepeterson_state.cfg.use_nameserver) &&
params->name != NULL) {
retval = nameserver_remove(gatepeterson_state.nshandle,
params->name);
retval = nameserver_remove_entry(gatepeterson_state.nshandle,
obj->ns_key);
if (unlikely(retval != 0))
goto error_handle;
kfree(params->name);
obj->ns_key = NULL;
}
mutex_unlock(obj->local_gate);
/* If the lock handle was created internally */
switch (obj->params.local_protection) {
case GATEPETERSON_PROTECT_NONE: /* Fall through */
case GATEPETERSON_PROTECT_INTERRUPT: /* Fall through */
obj->local_gate = NULL; /* TBD: Fixme */
break;
case GATEPETERSON_PROTECT_INTERRUPT: /* Fall through */
case GATEPETERSON_PROTECT_TASKLET: /* Fall through */
case GATEPETERSON_PROTECT_THREAD: /* Fall through */
case GATEPETERSON_PROTECT_PROCESS:
......@@ -495,26 +480,26 @@ static bool gatepeterson_inc_refcount(const struct gatepeterson_params *params,
if (params->shared_addr != NULL) {
if (obj->params.shared_addr == params->shared_addr) {
retval = mutex_lock_interruptible(
gatepeterson_state.list_lock);
gatepeterson_state.mod_lock);
if (retval)
break;
obj->ref_count++;
*handle = obj->top;
mutex_unlock(gatepeterson_state.list_lock);
mutex_unlock(gatepeterson_state.mod_lock);
done = true;
break;
}
} else if (params->name != NULL) {
} else if (params->name != NULL && obj->params.name != NULL) {
if (strcmp(obj->params.name, params->name) == 0) {
retval = mutex_lock_interruptible(
gatepeterson_state.list_lock);
gatepeterson_state.mod_lock);
if (retval)
break;
obj->ref_count++;
*handle = obj->top;
mutex_unlock(gatepeterson_state.list_lock);
mutex_unlock(gatepeterson_state.mod_lock);
done = true;
break;
}
......@@ -527,25 +512,22 @@ static bool gatepeterson_inc_refcount(const struct gatepeterson_params *params,
/*
* ======== gatepeterson_open ========
* Purpose:
* This will opens a created instance of GatePeterson
* This will opens a created instance of gatepeterson
* module.
*/
int gatepeterson_open(void **gphandle,
const struct gatepeterson_params *params)
struct gatepeterson_params *params)
{
struct gatepeterson_object *handle = NULL;
struct gatepeterson_obj *obj = NULL;
void *temp = NULL;
s32 retval = 0;
s32 status;
u32 sharedaddr;
u32 len;
void *entry = NULL;
BUG_ON(params == NULL);
BUG_ON(gphandle == NULL);
if (WARN_ON(gatepeterson_state.is_init != true)) {
retval = -EINVAL;
if (atomic_cmpmask_and_lt(&(gatepeterson_state.ref_count),
GATEPETERSON_MAKE_MAGICSTAMP(0),
GATEPETERSON_MAKE_MAGICSTAMP(1)) == true) {
retval = -ENODEV;
goto exit;
}
......@@ -576,11 +558,15 @@ int gatepeterson_open(void **gphandle,
retval = nameserver_get(gatepeterson_state.nshandle,
params->name, &sharedaddr,
sizeof(u32), NULL);
if (retval != 0)
if (retval < 0)
goto noentry_fail; /* Entry not found */
params->shared_addr = sharedregion_get_ptr(
(u32 *)sharedaddr);
if (params->shared_addr == NULL)
goto noentry_fail;
}
}
} else
sharedaddr = (u32)params->shared_addr;
if (unlikely(((struct gatepeterson_attrs *)sharedaddr)->status !=
GATEPETERSON_CREATED)) {
......@@ -588,108 +574,16 @@ int gatepeterson_open(void **gphandle,
goto noentry_fail;
}
handle = kmalloc(sizeof(struct gatepeterson_object), GFP_KERNEL);
if (handle == NULL) {
retval = -ENOMEM;
goto handle_alloc_fail;
}
obj = kmalloc(sizeof(struct gatepeterson_obj), GFP_KERNEL);
if (obj == NULL) {
retval = -ENOMEM; /* Not created */
goto obj_alloc_fail;
}
if (likely(gatepeterson_state.cfg.use_nameserver == true &&
params->name != NULL)) {
len = strlen(params->name) + 1;
obj->params.name = kmalloc(len, GFP_KERNEL);
if (obj->params.name == NULL) {
retval = -ENOMEM;
goto name_alloc_fail;
}
strncpy(obj->params.name, params->name, len);
entry = nameserver_add_uint32(gatepeterson_state.nshandle,
params->name, sharedaddr);
if (entry == NULL)
goto ns_add32_fail;
}
handle->obj = obj;
handle->enter = gatepeterson_enter;
handle->leave = gatepeterson_leave;
handle->lock_get_knl_handle = gatepeterson_get_knl_handle;
/* assign the memory with proper cache line padding */
obj->attrs = (struct gatepeterson_attrs *)sharedaddr;
obj->flag[0] = ((void *)(((u32)obj->attrs) + 128));
obj->flag[1] = ((void *)(((u32) obj->flag[0]) + 128));
obj->turn = ((void *)(((u32) obj->flag[1]) + 128)); /* TBD: Fixme */
/* Creator always has selfid set to 0 */
obj->self_id = 1;
obj->other_id = 0;
obj->nested = 0;
obj->ref_count = 0;
obj->attrs->opener_proc_id = multiproc_get_id(NULL);
obj->top = handle;
/* Create the local lock if not provided */
if (likely(params->local_protection ==
GATEPETERSON_PROTECT_DEFAULT))
obj->params.local_protection =
gatepeterson_state.cfg.default_protection;
else
obj->params.local_protection = params->local_protection;
switch (obj->params.local_protection) {
case GATEPETERSON_PROTECT_NONE: /* Fall through */
case GATEPETERSON_PROTECT_INTERRUPT: /* Fall through */
obj->local_gate = NULL; /* TBD: Fixme */
break;
case GATEPETERSON_PROTECT_TASKLET: /* Fall through */
case GATEPETERSON_PROTECT_THREAD: /* Fall through */
case GATEPETERSON_PROTECT_PROCESS:
obj->local_gate = kmalloc(sizeof(struct mutex), GFP_KERNEL);
if (obj->local_gate == NULL) {
retval = -ENOMEM;
goto gate_create_fail;
}
mutex_init(obj->local_gate);
break;
default:
/* An invalid protection level was supplied, FIXME */
break;
if (unlikely(((struct gatepeterson_attrs *)sharedaddr)->version !=
GATEPETERSON_VERSION)) {
retval = -ENXIO; /* FIXME Version mismatch,
need to change retval */
goto noentry_fail;
}
/* Populate the params member */
memcpy(&obj->params, params, sizeof(struct gatepeterson_params));
/* Put in the local list */
retval = mutex_lock_interruptible(gatepeterson_state.list_lock);
if (retval)
goto list_lock_fail;
list_add_tail(&obj->elem, &gatepeterson_state.obj_list);
mutex_unlock(gatepeterson_state.list_lock);
*gphandle = handle;
*gphandle = _gatepeterson_create(params, false);
return 0;
list_lock_fail:
kfree(obj->local_gate);
gate_create_fail:
status = nameserver_remove(gatepeterson_state.nshandle, params->name);
ns_add32_fail:
kfree(obj->params.name);
name_alloc_fail:
kfree(obj);
obj_alloc_fail:
kfree(handle);
handle_alloc_fail: /* Fall through */
noentry_fail: /* Fall through */
exit:
printk(KERN_ERR "gatepeterson_open failed status: %x\n", retval);
......@@ -701,7 +595,7 @@ EXPORT_SYMBOL(gatepeterson_open);
* ======== gatepeterson_close ========
* Purpose:
* This will closes previously opened/created instance
* of GatePeterson module
* of gatepeterson module
*/
int gatepeterson_close(void **gphandle)
{
......@@ -711,8 +605,10 @@ int gatepeterson_close(void **gphandle)
s32 retval = 0;
BUG_ON(gphandle == NULL);
if (WARN_ON(gatepeterson_state.is_init != true)) {
retval = -EINVAL;
if (atomic_cmpmask_and_lt(&(gatepeterson_state.ref_count),
GATEPETERSON_MAKE_MAGICSTAMP(0),
GATEPETERSON_MAKE_MAGICSTAMP(1)) == true) {
retval = -ENODEV;
goto exit;
}
......@@ -733,31 +629,23 @@ int gatepeterson_close(void **gphandle)
goto exit;
}
retval = mutex_lock_interruptible(gatepeterson_state.list_lock);
retval = mutex_lock_interruptible(gatepeterson_state.mod_lock);
if (retval)
goto error_handle;
list_del(&obj->elem);
mutex_unlock(gatepeterson_state.list_lock);
mutex_unlock(gatepeterson_state.mod_lock);
params = &obj->params;
/* remove from the name server */
if (likely(gatepeterson_state.cfg.use_nameserver == true &&
params->name != NULL)) {
retval = nameserver_remove(gatepeterson_state.nshandle,
params->name);
if (unlikely(retval != 0))
goto error_handle;
if (likely(params->name != NULL))
kfree(params->name);
}
mutex_unlock(obj->local_gate);
/* If the lock handle was created internally */
switch (obj->params.local_protection) {
case GATEPETERSON_PROTECT_NONE: /* Fall through */
case GATEPETERSON_PROTECT_INTERRUPT: /* Fall through */
obj->local_gate = NULL; /* TBD: Fixme */
break;
case GATEPETERSON_PROTECT_INTERRUPT: /* Fall through */
case GATEPETERSON_PROTECT_TASKLET: /* Fall through */
case GATEPETERSON_PROTECT_THREAD: /* Fall through */
case GATEPETERSON_PROTECT_PROCESS:
......@@ -785,7 +673,7 @@ EXPORT_SYMBOL(gatepeterson_close);
/*
* ======== gatepeterson_enter ========
* Purpose:
* This will enters the GatePeterson instance
* This will enters the gatepeterson instance
*/
u32 gatepeterson_enter(void *gphandle)
{
......@@ -794,13 +682,17 @@ u32 gatepeterson_enter(void *gphandle)
s32 retval = 0;
BUG_ON(gphandle == NULL);
if (WARN_ON(gatepeterson_state.is_init != true)) {
retval = -EINVAL;
if (WARN_ON(atomic_cmpmask_and_lt(&(gatepeterson_state.ref_count),
GATEPETERSON_MAKE_MAGICSTAMP(0),
GATEPETERSON_MAKE_MAGICSTAMP(1)) == true)) {
retval = -ENODEV;
goto exit;
}
handle = (struct gatepeterson_object *)gphandle;
obj = (struct gatepeterson_obj *) handle->obj;
if (obj->local_gate != NULL)
retval = mutex_lock_interruptible(obj->local_gate);
if (retval)
goto exit;
......@@ -814,9 +706,9 @@ u32 gatepeterson_enter(void *gphandle)
/* Wait while other processor is using the resource and has
* the turn
*/
while ((*((u32 *) obj->flag[obj->other_id])
while ((*((volatile u32 *) obj->flag[obj->other_id])
== GATEPETERSON_BUSY) &&
(*((u32 *)obj->turn) == obj->other_id))
(*((volatile u32 *)obj->turn) == obj->other_id))
; /* Empty body loop */
}
......@@ -830,14 +722,18 @@ EXPORT_SYMBOL(gatepeterson_enter);
/*
* ======== gatepeterson_leave ========
* Purpose:
* This will leaves the GatePeterson instance
* This will leaves the gatepeterson instance
*/
void gatepeterson_leave(void *gphandle, u32 flag)
{
struct gatepeterson_object *handle = NULL;
struct gatepeterson_obj *obj = NULL;
BUG_ON(gatepeterson_state.is_init != true);
if (WARN_ON(atomic_cmpmask_and_lt(&(gatepeterson_state.ref_count),
GATEPETERSON_MAKE_MAGICSTAMP(0),
GATEPETERSON_MAKE_MAGICSTAMP(1)) == true))
goto exit;
BUG_ON(gphandle == NULL);
handle = (struct gatepeterson_object *)gphandle;
......@@ -845,9 +741,12 @@ void gatepeterson_leave(void *gphandle, u32 flag)
obj = (struct gatepeterson_obj *)handle->obj;
obj->nested--;
if (obj->nested == 0)
*((u32 *) obj->flag[obj->self_id]) = GATEPETERSON_FREE ;
*((volatile u32 *)obj->flag[obj->self_id]) = GATEPETERSON_FREE;
if (obj->local_gate != NULL)
mutex_unlock(obj->local_gate);
exit:
return;
}
EXPORT_SYMBOL(gatepeterson_leave);
......@@ -874,12 +773,176 @@ u32 gatepeterson_shared_memreq(const struct gatepeterson_params *params)
{
u32 retval = 0;
if (params != NULL)
retval = 128 * 4;
else
retval = 4 * sizeof(u32);
retval = (GATEPETERSON_CACHESIZE * 4) ;
return retval;
}
EXPORT_SYMBOL(gatepeterson_shared_memreq);
/*
* ======== gatepeterson_create ========
* Purpose:
* Creates a new instance of gatepeterson module.
* This is an internal function because both
* gatepeterson_create and gatepeterson_open
* call use the same functionality.
*/
static void *_gatepeterson_create(const struct gatepeterson_params *params,
bool create_flag)
{
int status = 0;
struct gatepeterson_object *handle = NULL;
struct gatepeterson_obj *obj = NULL;
u32 len;
u32 shm_index;
u32 shared_shm_base;
s32 retval = 0;
handle = kmalloc(sizeof(struct gatepeterson_object), GFP_KERNEL);
if (handle == NULL) {
retval = -ENOMEM;
goto exit;
}
obj = kmalloc(sizeof(struct gatepeterson_obj), GFP_KERNEL);
if (obj == NULL) {
retval = -ENOMEM;
goto obj_alloc_fail;
}
if (likely(gatepeterson_state.cfg.use_nameserver == true &&
params->name != NULL)) {
len = strlen(params->name) + 1;
obj->params.name = kmalloc(len, GFP_KERNEL);
if (obj->params.name == NULL) {
retval = -ENOMEM;
goto name_alloc_fail;
}
if (create_flag == true) {
shm_index = sharedregion_get_index(
params->shared_addr);
shared_shm_base = (u32)sharedregion_get_srptr(
(void *)params->shared_addr,
shm_index);
obj->ns_key = nameserver_add_uint32(
gatepeterson_state.nshandle,
params->name,
(u32) (shared_shm_base));
if (obj->ns_key == NULL) {
status = -ENOMEM; /* FIXME */
goto ns_add32_fail;
}
}
}
handle->obj = obj;
handle->enter = &gatepeterson_enter;
handle->leave = &gatepeterson_leave;
handle->lock_get_knl_handle = &gatepeterson_get_knl_handle;
/* assign the memory with proper cache line padding */
obj->attrs = (struct gatepeterson_attrs *) params->shared_addr;
obj->flag[0] = ((void *)(((u32) obj->attrs) +
GATEPETERSON_CACHESIZE));
obj->flag[1] = ((void *)(((u32) obj->flag[0]) +
GATEPETERSON_CACHESIZE));
obj->turn = ((void *)(((u32) obj->flag[1])
+ GATEPETERSON_CACHESIZE)); /* TBD: Fixme */
/* Creator always has selfid set to 0 */
if (create_flag == true) {
obj->self_id = 0;
obj->other_id = 1;
obj->attrs->creator_proc_id = multiproc_get_id(NULL);
obj->attrs->opener_proc_id = MULTIPROC_INVALIDID;
obj->attrs->status = GATEPETERSON_CREATED;
obj->attrs->version = GATEPETERSON_VERSION;
/* Set up shared memory */
*(obj->turn) = 0x0;
*(obj->flag[0]) = 0x0;
*(obj->flag[1]) = 0x0;
obj->ref_count = 0;
} else {
obj->self_id = 1;
obj->other_id = 0;
obj->attrs->opener_proc_id = multiproc_get_id(NULL);
obj->ref_count = 1;
}
obj->nested = 0;
obj->top = handle;
/* Create the local lock if not provided */
if (likely(params->local_protection == GATEPETERSON_PROTECT_DEFAULT))
obj->params.local_protection =
gatepeterson_state.cfg.default_protection;
else
obj->params.local_protection = params->local_protection;
switch (obj->params.local_protection) {
case GATEPETERSON_PROTECT_NONE: /* Fall through */
obj->local_gate = NULL; /* TBD: Fixme */
break;
/* In syslink ; for interrupt protect gatespinlock is used, that
* internally uses the mutex. So we added mutex for interrupt
* protection here also
*/
case GATEPETERSON_PROTECT_INTERRUPT: /* Fall through */
case GATEPETERSON_PROTECT_TASKLET: /* Fall through */
case GATEPETERSON_PROTECT_THREAD: /* Fall through */
case GATEPETERSON_PROTECT_PROCESS:
obj->local_gate = kmalloc(sizeof(struct mutex), GFP_KERNEL);
if (obj->local_gate == NULL) {
retval = -ENOMEM;
goto gate_create_fail;
}
mutex_init(obj->local_gate);
break;
default:
/* An invalid protection level was supplied, FIXME */
obj->local_gate = NULL;
break;
}
/* Populate the params member */
memcpy(&obj->params, params, sizeof(struct gatepeterson_params));
/* Put in the local list */
retval = mutex_lock_interruptible(gatepeterson_state.mod_lock);
if (retval)
goto mod_lock_fail;
list_add_tail(&obj->elem, &gatepeterson_state.obj_list);
mutex_unlock(gatepeterson_state.mod_lock);
return (void *)handle;
mod_lock_fail:
kfree(obj->local_gate);
gate_create_fail:
status = nameserver_remove_entry(gatepeterson_state.nshandle,
obj->ns_key);
ns_add32_fail:
kfree(obj->params.name);
name_alloc_fail:
kfree(obj);
obj_alloc_fail:
kfree(handle);
handle = NULL;
exit:
if (create_flag == true)
printk(KERN_ERR "gatepeterson_create failed status: %x\n",
retval);
else
printk(KERN_ERR "gatepeterson_open failed status: %x\n",
retval);
return NULL;
}
......@@ -36,12 +36,13 @@ static int gatepeterson_ioctl_get_config(struct gatepeterson_cmd_args *cargs)
s32 status = 0;
s32 size;
cargs->api_status = gatepeterson_get_config(&config);
gatepeterson_get_config(&config);
size = copy_to_user(cargs->args.get_config.config, &config,
sizeof(struct gatepeterson_config));
if (size)
status = -EFAULT;
cargs->api_status = 0;
return status;
}
......@@ -92,12 +93,14 @@ static int gatepeterson_ioctl_params_init(struct gatepeterson_cmd_args *cargs)
s32 status = 0;
s32 size;
cargs->api_status = gatepeterson_params_init(&params);
gatepeterson_params_init(cargs->args.params_init.handle,
&params);
size = copy_to_user(cargs->args.params_init.params, &params,
sizeof(struct gatepeterson_params));
if (size)
status = -EFAULT;
cargs->api_status = 0;
return status;
}
......@@ -139,7 +142,8 @@ static int gatepeterson_ioctl_create(struct gatepeterson_cmd_args *cargs)
}
params.shared_addr = sharedregion_get_ptr((u32 *)params.shared_addr);
params.shared_addr = sharedregion_get_ptr(
(u32 *)cargs->args.create.shared_addr_srptr);
handle = gatepeterson_create(&params);
/* Here we are not validating the return from the module.
Even it is nul, we pass it to user and user has to pass
......@@ -205,7 +209,8 @@ static int gatepeterson_ioctl_open(struct gatepeterson_cmd_args *cargs)
}
}
params.shared_addr = sharedregion_get_ptr((u32 *)params.shared_addr);
params.shared_addr = sharedregion_get_ptr(
(u32 *)cargs->args.create.shared_addr_srptr);
cargs->api_status = gatepeterson_open(&handle, &params);
cargs->args.open.handle = handle;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment