why to use these weird nesting structure - linux

i'm trying to study the linux kernel and reading the kernel code,
but i can't understand the structure they use for the page structure as shown below:
i mean,why they use union nested in the struct which nested in the union
(the code is simplified...)
struct page {
unsigned long flags;
struct address_space *mapping;
struct {
union {
pgoff_t index;
void *freelist;
};
union {
unsigned counters;
struct {
union {
atomic_t _mapcount;
struct {
unsigned inuse:16;
unsigned objects:15;
unsigned frozen:1;
};
};
atomic_t _count;
};
};
};
}

It is used to bring clarity into the code. It will be easier to read and understand if members are grouped.
Since you are not using the 'sub-structures' in any other data-structure, they are nested. Else, they would be declared separate and included as members, like below:
struct list_based{
pgoff_t index;
void *freelist;
};
struct page {
unsigned long flags;
struct address_space *mapping;
struct list_based lpage;
};
struct sector {
unsigned long sub sect;
struct list_based lsect;
};

Related

the definition of spinlock_t in linux kernel

in include/linux/spinlock_types.h
the definition of spinlock_t like below
typedef struct spinlock {
union {
struct raw_spinlock rlock;
struct {
u8 __padding[];
struct lockdep_map dep_map;
};
};
} spinlock_t;
why the "__padding[]" and "dep_map" variable should put inside a struct which has no name
but not just like below?
typedef struct spinlock {
union {
struct raw_spinlock rlock;
u8 __padding[];
struct lockdep_map dep_map;
};
} spinlock_t;
is there any special meaning?
thank you
Because it is union of two structures and the other structure is enabled during debugging.
What you are trying to do is creating structure members that are not needed at all.And you should understand in union of two structures we can use one at a time.
typedef struct spinlock {
union {
struct raw_spinlock rlock;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
# define LOCK_PADSIZE (offsetof(struct raw_spinlock, dep_map))
struct {
u8 __padding[LOCK_PADSIZE];
struct lockdep_map dep_map;
};
#endif
};
} spinlock_t;

Use structure member within s a structure using typedef

When I compile the following I get use of undeclared identifier 'rsdtHeader'
How can I do the following operation using typedef?
typedef struct
{
int length;
int x;
int y;
} SdtHeader_s;
typedef struct
{
SdtHeader_s rsdtHeader;
SdtHeader_s* rsdtEntry[(rsdtHeader.length - sizeof(rsdtHeader))/4];
} Rsdt_s;

why struct cdev has kobject member?

It's strange that struct cdev has struct kobject member, do any body knows the reason?
When kobjects are embedded inside other structures, the structures receive the standardized functions that a kobject provides. Most importantly, the structure's embedded kobject now enables the structure to become part of an object hierarchy. For example the cdev structure is presentable in an object hierarchy via the parent pointer cdev->kobj.parent and the list cdev->kobj.entry
Source: Linux Kernel Development by Robert Love
Sysfs is a Virtual filesystem that describes the devices available to the system in hierarchical pattern. This is done by using struct kobj.
struct kobject {
char *k_name;
char name[KOBJ_NAME_LEN];
struct kref kref;
struct list_head entry;
struct kobject *parent;
struct kset *kset;
struct kobj_type *ktype;
struct dentry *dentry;
};
For any driver kobj is required to export the device attributes to sysfs
if we consider like i2c_client spi_device(spi client). we have kobj inside member struct dev to export the driver attributes to the user space virtual filesystem(Sysfs). The Kobj structure members handles all the operations including referring to the device numbers(major/minor) and file operations involved for open, read/write,close etc... of device.
In your case cdev_init & cdev_add will internally uses kobj to do the above operation.
There are two reasons:
for reference counting, which is offered by kref internally.
static struct kobject *cdev_get(struct cdev *p)
{
struct module *owner = p->owner;
struct kobject *kobj;
if (owner && !try_module_get(owner))
return NULL;
kobj = kobject_get_unless_zero(&p->kobj);
if (!kobj)
module_put(owner);
return kobj;
}
void cdev_put(struct cdev *p)
{
if (p) {
struct module *owner = p->owner;
kobject_put(&p->kobj);
module_put(owner);
}
}
for release, that's also why kref is not enough(kref doesn't have a release hook).
static void cdev_default_release(struct kobject *kobj)
{
struct cdev *p = container_of(kobj, struct cdev, kobj);
struct kobject *parent = kobj->parent;
cdev_purge(p);
kobject_put(parent);
}
static void cdev_dynamic_release(struct kobject *kobj)
{
struct cdev *p = container_of(kobj, struct cdev, kobj);
struct kobject *parent = kobj->parent;
cdev_purge(p);
kfree(p);
kobject_put(parent);
}
static struct kobj_type ktype_cdev_default = {
.release = cdev_default_release,
};
static struct kobj_type ktype_cdev_dynamic = {
.release = cdev_dynamic_release,
};

Marshalling nested Structs in C to C#

I'm again stuck with marshalling C structs into C#. Here is what I want to marshal to C#.
The C function signature is as below
int GetParametersDescription(unsigned int *numParams,
OP_PARAMETER_INFO **parameterInfo,
unsigned int *numVars,
OP_VARIABLE_INFO **variableInfo);
Output Arguments
numParams: number of model’s parameters.
parameterInfo: List of parameters’ structures returned.Size of the list is numParams.
numVars: number of model’s variables.
variableInfo: List of variables’ structures returned.Size of the list is numVars.
OP_PARAMETER_INFO struct signature in C
typedef struct OP_PARAMETER_INFO {
unsigned id; // Parameter Id
char *path; // Parameter's path in the model
char *name; // Parameter's label if any
char *alias; // Parameter's alias if any.
struct OP_VARIABLE_INFO *varInfo; // Pointer on OP_VARIABLE_INFO if variable exist
unsigned nbRows; // Number of rows for this parameter
unsigned nbCols; // Number of cols for this parameter
double *values; // List of values, nbValue = nbRows * nbCols
OP_SEARCH_RESULTS exist; // This is an enum
unsigned newParamId; // ID of the estimated parameter if does not exist
} OP_PARAMETER_INFO;
OP_VARIABLE_INFO struct signature in C
typedef struct OP_VARIABLE_INFO {
unsigned id; // Variable Id
char *name; // Variable name
unsigned int nbParams; // Number of parameters associated with the variable
struct OP_PARAMETER_INFO** param; // List of pointers of OP_PARAMETER_INFO structure
} OP_VARIABLE_INFO;
OP_SEARCH_RESULTS is an enum and the signature look as below
typedef enum {
OP_SEARCH_NOT_FOUND,
OP_SEARCH_FOUND_EXACT,
OP_SEARCH_FOUND_DIFFERENT,
OP_SEARCH_FOUND_ESTIMATION
} OP_SEARCH_RESULTS;
I did try out making structs in C#, but none of them seem to work.
Could you pls help me defining these structs in C# and calling them in P/invoke methods and to extract the structs information.....

How is OpenCL floatn different from a custom struct

I'm having problems passing a structure of vectors to an OpenCL kernel.
Long story short, I have found that I CAN pass a C structure:
typedef struct {
cl_float4 vec;
} my_type;
. . . to a kernel, if I declare it like:
typedef struct { float s[4]; } my_float4;
typedef struct { my_float4 vec; } my_type; //use custom float4
__kernel void function(const my_type test) {}
. . . but NOT, if I declare it like:
typedef struct { float4 vec; } my_type; //use built-in float4
__kernel void function(const my_type test) {}
So my question is, what makes a float4 different and special? In the second example, I get CL_INVALID_ARG_SIZE on clSetKernelArg. In the host code, I'm using cl_float4--isn't that supposed to be paired with float4 in the kernel?
EDIT: by request, the clSetKernelArg code (error handling cropped):
template <typename type_data> void set_argument(int arg_index, const type_data* data) {
cl_int err = clSetKernelArg(kernel,arg_index,sizeof(type_data),data);
if (err!=CL_SUCCESS) throw "ERROR"; /*simplified*/
}
I call the function with a struct declared exactly as above:
my_type test;
my_kernel->set_argument(0,&test);
This sounds like a bug with your implementation - you should be able to pass that user-defined type to a kernel without issue. What platform / SDK are you using? I was able to successfully declare this type in host code:
typedef struct _mytype {
cl_float4 val;
} mytype;
... and then later use it:
mytype t;
status = clSetKernelArg(kernel, argc++, sizeof(mytype), &t);
check_status("clSetKernelArg:mytype t", status);
Where check_status does what you'd expect: checks for a non-CL_SUCCESS return value.
The kernel looks like this:
typedef struct _mytype {
float4 value;
} mytype;
kernel void do_it(/* ... */, const mytype test) { /* ... */ }
This compiles and executes, giving correct results on the CPU device.

Resources